autotel 4.3.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. package/README.md +125 -103
  2. package/dist/analysis.cjs +87 -0
  3. package/dist/analysis.cjs.map +1 -0
  4. package/dist/analysis.d.cts +87 -0
  5. package/dist/analysis.d.cts.map +1 -0
  6. package/dist/analysis.d.ts +87 -0
  7. package/dist/analysis.d.ts.map +1 -0
  8. package/dist/analysis.js +85 -0
  9. package/dist/analysis.js.map +1 -0
  10. package/dist/{attribute-redacting-processor-DtTS9xxh.d.ts → attribute-redacting-processor-Pk7lAzWd.d.cts} +13 -8
  11. package/dist/attribute-redacting-processor-Pk7lAzWd.d.cts.map +1 -0
  12. package/dist/{attribute-redacting-processor-DtTS9xxh.d.cts → attribute-redacting-processor-Pk7lAzWd.d.ts} +13 -8
  13. package/dist/attribute-redacting-processor-Pk7lAzWd.d.ts.map +1 -0
  14. package/dist/attribute-redacting-processor.cjs +4 -4
  15. package/dist/attribute-redacting-processor.cjs.map +1 -1
  16. package/dist/attribute-redacting-processor.d.cts +1 -1
  17. package/dist/attribute-redacting-processor.d.ts +1 -1
  18. package/dist/attribute-redacting-processor.js +4 -4
  19. package/dist/attribute-redacting-processor.js.map +1 -1
  20. package/dist/attributes.d.cts +1 -1
  21. package/dist/attributes.d.ts +1 -1
  22. package/dist/auto.cjs +1 -1
  23. package/dist/auto.cjs.map +1 -1
  24. package/dist/auto.d.cts +1 -1
  25. package/dist/auto.d.ts +1 -1
  26. package/dist/auto.js +1 -1
  27. package/dist/auto.js.map +1 -1
  28. package/dist/business-baggage.d.cts +2 -3
  29. package/dist/business-baggage.d.cts.map +1 -1
  30. package/dist/business-baggage.d.ts +2 -3
  31. package/dist/business-baggage.d.ts.map +1 -1
  32. package/dist/{canonical-log-line-processor-xvjMgtpF.d.cts → canonical-log-line-processor-B4WgG-VS.d.cts} +2 -3
  33. package/dist/canonical-log-line-processor-B4WgG-VS.d.cts.map +1 -0
  34. package/dist/{canonical-log-line-processor-BcRuAdRk.d.ts → canonical-log-line-processor-CL_J7gb5.d.ts} +2 -3
  35. package/dist/canonical-log-line-processor-CL_J7gb5.d.ts.map +1 -0
  36. package/dist/{canonical-log-line-processor-CcrDi6TO.cjs → canonical-log-line-processor-DOjb6Kxy.cjs} +5 -5
  37. package/dist/canonical-log-line-processor-DOjb6Kxy.cjs.map +1 -0
  38. package/dist/{canonical-log-line-processor-FLezvFCB.js → canonical-log-line-processor-mKABvGP0.js} +5 -5
  39. package/dist/canonical-log-line-processor-mKABvGP0.js.map +1 -0
  40. package/dist/config.d.cts +12 -7
  41. package/dist/config.d.cts.map +1 -1
  42. package/dist/config.d.ts +12 -7
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/correlation-id.cjs +9 -9
  45. package/dist/correlation-id.d.cts +0 -1
  46. package/dist/correlation-id.d.cts.map +1 -1
  47. package/dist/correlation-id.d.ts +0 -1
  48. package/dist/correlation-id.d.ts.map +1 -1
  49. package/dist/correlation-id.js +1 -1
  50. package/dist/db.d.cts.map +1 -1
  51. package/dist/db.d.ts.map +1 -1
  52. package/dist/decorators.cjs +2 -2
  53. package/dist/decorators.cjs.map +1 -1
  54. package/dist/decorators.d.cts +1 -2
  55. package/dist/decorators.d.cts.map +1 -1
  56. package/dist/decorators.d.ts +1 -2
  57. package/dist/decorators.d.ts.map +1 -1
  58. package/dist/decorators.js +1 -1
  59. package/dist/decorators.js.map +1 -1
  60. package/dist/{define-event-CreknLm3.d.ts → define-event-B2z1SBe7.d.ts} +2 -3
  61. package/dist/define-event-B2z1SBe7.d.ts.map +1 -0
  62. package/dist/{define-event-HZRizPwz.d.cts → define-event-CGG048HE.d.cts} +2 -3
  63. package/dist/define-event-CGG048HE.d.cts.map +1 -0
  64. package/dist/diagnostics.cjs +10 -1
  65. package/dist/diagnostics.cjs.map +1 -1
  66. package/dist/diagnostics.d.cts +0 -1
  67. package/dist/diagnostics.d.cts.map +1 -1
  68. package/dist/diagnostics.d.ts +0 -1
  69. package/dist/diagnostics.d.ts.map +1 -1
  70. package/dist/diagnostics.js +10 -1
  71. package/dist/diagnostics.js.map +1 -1
  72. package/dist/drain-pipeline.d.cts +12 -5
  73. package/dist/drain-pipeline.d.cts.map +1 -1
  74. package/dist/drain-pipeline.d.ts +12 -5
  75. package/dist/drain-pipeline.d.ts.map +1 -1
  76. package/dist/enrichers.d.cts.map +1 -1
  77. package/dist/enrichers.d.ts.map +1 -1
  78. package/dist/{event-subscriber-D1XLkPzi.d.ts → event-subscriber-CWh8sTGh.d.cts} +2 -2
  79. package/dist/event-subscriber-CWh8sTGh.d.cts.map +1 -0
  80. package/dist/{event-subscriber-D1XLkPzi.d.cts → event-subscriber-CWh8sTGh.d.ts} +2 -2
  81. package/dist/event-subscriber-CWh8sTGh.d.ts.map +1 -0
  82. package/dist/event-subscriber.d.cts +1 -1
  83. package/dist/event-subscriber.d.ts +1 -1
  84. package/dist/{event-testing-CfFs3to2.d.ts → event-testing-CA2mIx1E.d.ts} +2 -3
  85. package/dist/event-testing-CA2mIx1E.d.ts.map +1 -0
  86. package/dist/{event-testing-BqRnI0z4.d.cts → event-testing-D0qWfqAy.d.cts} +2 -3
  87. package/dist/event-testing-D0qWfqAy.d.cts.map +1 -0
  88. package/dist/event-testing.d.cts +1 -1
  89. package/dist/event-testing.d.ts +1 -1
  90. package/dist/event.cjs +4 -4
  91. package/dist/event.d.cts +3 -4
  92. package/dist/event.d.cts.map +1 -1
  93. package/dist/event.d.ts +3 -4
  94. package/dist/event.d.ts.map +1 -1
  95. package/dist/event.js +1 -1
  96. package/dist/exporters.d.cts +0 -4
  97. package/dist/exporters.d.cts.map +1 -1
  98. package/dist/exporters.d.ts +0 -4
  99. package/dist/exporters.d.ts.map +1 -1
  100. package/dist/{filtering-span-processor-B8R8B7Uk.d.ts → filtering-span-processor-BpDagWNa.d.cts} +1 -2
  101. package/dist/filtering-span-processor-BpDagWNa.d.cts.map +1 -0
  102. package/dist/{filtering-span-processor-B8R8B7Uk.d.cts → filtering-span-processor-BpDagWNa.d.ts} +1 -2
  103. package/dist/filtering-span-processor-BpDagWNa.d.ts.map +1 -0
  104. package/dist/filtering-span-processor.d.cts +1 -1
  105. package/dist/filtering-span-processor.d.ts +1 -1
  106. package/dist/functional-BnDUxnSl.js +838 -0
  107. package/dist/functional-BnDUxnSl.js.map +1 -0
  108. package/dist/functional-DcLBuCPz.cjs +888 -0
  109. package/dist/functional-DcLBuCPz.cjs.map +1 -0
  110. package/dist/functional.cjs +2 -2
  111. package/dist/functional.d.cts +79 -130
  112. package/dist/functional.d.cts.map +1 -1
  113. package/dist/functional.d.ts +79 -130
  114. package/dist/functional.d.ts.map +1 -1
  115. package/dist/functional.js +2 -2
  116. package/dist/http.cjs +6 -6
  117. package/dist/http.cjs.map +1 -1
  118. package/dist/http.d.cts +4 -5
  119. package/dist/http.d.cts.map +1 -1
  120. package/dist/http.d.ts +4 -5
  121. package/dist/http.d.ts.map +1 -1
  122. package/dist/http.js +5 -5
  123. package/dist/http.js.map +1 -1
  124. package/dist/{index-eKuioqT1.d.cts → index-BPcxVucm.d.cts} +2 -3
  125. package/dist/index-BPcxVucm.d.cts.map +1 -0
  126. package/dist/{index-Ck06vlW2.d.ts → index-DolOVX6F.d.ts} +2 -3
  127. package/dist/index-DolOVX6F.d.ts.map +1 -0
  128. package/dist/index.cjs +25 -167
  129. package/dist/index.cjs.map +1 -1
  130. package/dist/index.d.cts +14 -14
  131. package/dist/index.d.cts.map +1 -1
  132. package/dist/index.d.ts +14 -14
  133. package/dist/index.d.ts.map +1 -1
  134. package/dist/index.js +6 -148
  135. package/dist/index.js.map +1 -1
  136. package/dist/init-C3RApHKJ.cjs +3371 -0
  137. package/dist/init-C3RApHKJ.cjs.map +1 -0
  138. package/dist/{init-DSrRmVnz.d.cts → init-D6n2diBy.d.ts} +46 -20
  139. package/dist/init-D6n2diBy.d.ts.map +1 -0
  140. package/dist/init-R-gSEXkJ.js +3190 -0
  141. package/dist/init-R-gSEXkJ.js.map +1 -0
  142. package/dist/{init-B7u-DjxM.d.ts → init-XzXzrarP.d.cts} +46 -20
  143. package/dist/init-XzXzrarP.d.cts.map +1 -0
  144. package/dist/instrumentation.cjs +7 -13
  145. package/dist/instrumentation.cjs.map +1 -1
  146. package/dist/instrumentation.d.cts +0 -1
  147. package/dist/instrumentation.d.cts.map +1 -1
  148. package/dist/instrumentation.d.ts +0 -1
  149. package/dist/instrumentation.d.ts.map +1 -1
  150. package/dist/instrumentation.js +8 -14
  151. package/dist/instrumentation.js.map +1 -1
  152. package/dist/{logger-BauSUhUv.d.ts → logger-CN4xpzMd.d.cts} +1 -2
  153. package/dist/logger-CN4xpzMd.d.cts.map +1 -0
  154. package/dist/{logger-BauSUhUv.d.cts → logger-CN4xpzMd.d.ts} +1 -2
  155. package/dist/logger-CN4xpzMd.d.ts.map +1 -0
  156. package/dist/logger-D3Ej3DII.js.map +1 -1
  157. package/dist/logger-thMPLpOG.cjs.map +1 -1
  158. package/dist/logger.d.cts +1 -1
  159. package/dist/logger.d.ts +1 -1
  160. package/dist/messaging-adapters.cjs.map +1 -1
  161. package/dist/messaging-adapters.d.cts +0 -1
  162. package/dist/messaging-adapters.d.cts.map +1 -1
  163. package/dist/messaging-adapters.d.ts +0 -1
  164. package/dist/messaging-adapters.d.ts.map +1 -1
  165. package/dist/messaging-adapters.js.map +1 -1
  166. package/dist/messaging-testing.d.cts +0 -1
  167. package/dist/messaging-testing.d.cts.map +1 -1
  168. package/dist/messaging-testing.d.ts +0 -1
  169. package/dist/messaging-testing.d.ts.map +1 -1
  170. package/dist/messaging.cjs +27 -10
  171. package/dist/messaging.cjs.map +1 -1
  172. package/dist/messaging.d.cts +6 -7
  173. package/dist/messaging.d.cts.map +1 -1
  174. package/dist/messaging.d.ts +6 -7
  175. package/dist/messaging.d.ts.map +1 -1
  176. package/dist/messaging.js +27 -10
  177. package/dist/messaging.js.map +1 -1
  178. package/dist/metric-helpers.d.cts +0 -1
  179. package/dist/metric-helpers.d.cts.map +1 -1
  180. package/dist/metric-helpers.d.ts +0 -1
  181. package/dist/metric-helpers.d.ts.map +1 -1
  182. package/dist/{metric-testing-DXdK3-Q3.d.ts → metric-testing-CWm6UhaR.d.ts} +2 -3
  183. package/dist/metric-testing-CWm6UhaR.d.ts.map +1 -0
  184. package/dist/{metric-testing-MxvzChDp.d.cts → metric-testing-CpvP3ZIa.d.cts} +2 -3
  185. package/dist/metric-testing-CpvP3ZIa.d.cts.map +1 -0
  186. package/dist/metric-testing.d.cts +1 -1
  187. package/dist/metric-testing.d.ts +1 -1
  188. package/dist/metric.d.cts +3 -4
  189. package/dist/metric.d.cts.map +1 -1
  190. package/dist/metric.d.ts +3 -4
  191. package/dist/metric.d.ts.map +1 -1
  192. package/dist/parse-error.d.cts.map +1 -1
  193. package/dist/parse-error.d.ts.map +1 -1
  194. package/dist/processors.cjs +1 -1
  195. package/dist/processors.d.cts +1 -1
  196. package/dist/processors.d.ts +1 -1
  197. package/dist/processors.js +1 -1
  198. package/dist/register.d.cts +1 -1
  199. package/dist/register.d.ts +1 -1
  200. package/dist/{sampling-DfYhDJij.d.cts → sampling-BR9fkSwx.d.cts} +127 -10
  201. package/dist/sampling-BR9fkSwx.d.cts.map +1 -0
  202. package/dist/{sampling-CR0Va1VB.d.ts → sampling-CP3e7-Yr.d.ts} +127 -10
  203. package/dist/sampling-CP3e7-Yr.d.ts.map +1 -0
  204. package/dist/sampling.cjs +160 -12
  205. package/dist/sampling.cjs.map +1 -1
  206. package/dist/sampling.d.cts +2 -2
  207. package/dist/sampling.d.ts +2 -2
  208. package/dist/sampling.js +157 -13
  209. package/dist/sampling.js.map +1 -1
  210. package/dist/security-schema.d.cts +9 -4
  211. package/dist/security-schema.d.cts.map +1 -1
  212. package/dist/security-schema.d.ts +9 -4
  213. package/dist/security-schema.d.ts.map +1 -1
  214. package/dist/semantic-conventions-FhSxv-bK.d.cts.map +1 -1
  215. package/dist/semantic-conventions-FhSxv-bK.d.ts.map +1 -1
  216. package/dist/semantic-conventions.cjs.map +1 -1
  217. package/dist/semantic-conventions.js.map +1 -1
  218. package/dist/semantic-helpers.cjs +85 -304
  219. package/dist/semantic-helpers.cjs.map +1 -1
  220. package/dist/semantic-helpers.d.cts +21 -12
  221. package/dist/semantic-helpers.d.cts.map +1 -1
  222. package/dist/semantic-helpers.d.ts +21 -12
  223. package/dist/semantic-helpers.d.ts.map +1 -1
  224. package/dist/semantic-helpers.js +85 -304
  225. package/dist/semantic-helpers.js.map +1 -1
  226. package/dist/slo.cjs +225 -0
  227. package/dist/slo.cjs.map +1 -0
  228. package/dist/slo.d.cts +97 -0
  229. package/dist/slo.d.cts.map +1 -0
  230. package/dist/slo.d.ts +97 -0
  231. package/dist/slo.d.ts.map +1 -0
  232. package/dist/slo.js +223 -0
  233. package/dist/slo.js.map +1 -0
  234. package/dist/{span-name-normalizer-8ZOGJuwv.d.ts → span-name-normalizer-CN1-8C76.d.cts} +1 -2
  235. package/dist/span-name-normalizer-CN1-8C76.d.cts.map +1 -0
  236. package/dist/{span-name-normalizer-8ZOGJuwv.d.cts → span-name-normalizer-CN1-8C76.d.ts} +1 -2
  237. package/dist/span-name-normalizer-CN1-8C76.d.ts.map +1 -0
  238. package/dist/span-name-normalizer.cjs.map +1 -1
  239. package/dist/span-name-normalizer.d.cts +1 -1
  240. package/dist/span-name-normalizer.d.ts +1 -1
  241. package/dist/span-name-normalizer.js.map +1 -1
  242. package/dist/tail-sampling-processor.d.cts +0 -1
  243. package/dist/tail-sampling-processor.d.cts.map +1 -1
  244. package/dist/tail-sampling-processor.d.ts +0 -1
  245. package/dist/tail-sampling-processor.d.ts.map +1 -1
  246. package/dist/test-span-collector.cjs.map +1 -1
  247. package/dist/test-span-collector.d.cts +0 -1
  248. package/dist/test-span-collector.d.cts.map +1 -1
  249. package/dist/test-span-collector.d.ts +0 -1
  250. package/dist/test-span-collector.d.ts.map +1 -1
  251. package/dist/test-span-collector.js.map +1 -1
  252. package/dist/testing.cjs +76 -11
  253. package/dist/testing.cjs.map +1 -1
  254. package/dist/testing.d.cts +30 -5
  255. package/dist/testing.d.cts.map +1 -1
  256. package/dist/testing.d.ts +30 -5
  257. package/dist/testing.d.ts.map +1 -1
  258. package/dist/testing.js +73 -12
  259. package/dist/testing.js.map +1 -1
  260. package/dist/{trace-context-Cijqoi6e.d.ts → trace-context-IuyoPyNq.d.cts} +9 -9
  261. package/dist/trace-context-IuyoPyNq.d.cts.map +1 -0
  262. package/dist/{trace-context-Cijqoi6e.d.cts → trace-context-IuyoPyNq.d.ts} +9 -9
  263. package/dist/trace-context-IuyoPyNq.d.ts.map +1 -0
  264. package/dist/trace-factory-validation-BjVAinz6.js +13 -0
  265. package/dist/trace-factory-validation-BjVAinz6.js.map +1 -0
  266. package/dist/trace-factory-validation-Dc8epn87.cjs +19 -0
  267. package/dist/trace-factory-validation-Dc8epn87.cjs.map +1 -0
  268. package/dist/trace-helpers.cjs +7 -7
  269. package/dist/trace-helpers.cjs.map +1 -1
  270. package/dist/trace-helpers.d.cts +6 -7
  271. package/dist/trace-helpers.d.cts.map +1 -1
  272. package/dist/trace-helpers.d.ts +6 -7
  273. package/dist/trace-helpers.d.ts.map +1 -1
  274. package/dist/trace-helpers.js +7 -7
  275. package/dist/trace-helpers.js.map +1 -1
  276. package/dist/tracer-provider.d.cts +0 -1
  277. package/dist/tracer-provider.d.cts.map +1 -1
  278. package/dist/tracer-provider.d.ts +0 -1
  279. package/dist/tracer-provider.d.ts.map +1 -1
  280. package/dist/validate.cjs.map +1 -1
  281. package/dist/validate.d.cts +1 -2
  282. package/dist/validate.d.cts.map +1 -1
  283. package/dist/validate.d.ts +1 -2
  284. package/dist/validate.d.ts.map +1 -1
  285. package/dist/validate.js.map +1 -1
  286. package/dist/validation-attributes.d.cts +17 -8
  287. package/dist/validation-attributes.d.cts.map +1 -1
  288. package/dist/validation-attributes.d.ts +17 -8
  289. package/dist/validation-attributes.d.ts.map +1 -1
  290. package/dist/webhook.cjs +5 -4
  291. package/dist/webhook.cjs.map +1 -1
  292. package/dist/webhook.d.cts +4 -4
  293. package/dist/webhook.d.cts.map +1 -1
  294. package/dist/webhook.d.ts +4 -4
  295. package/dist/webhook.d.ts.map +1 -1
  296. package/dist/webhook.js +5 -4
  297. package/dist/webhook.js.map +1 -1
  298. package/dist/workflow-distributed.cjs +5 -5
  299. package/dist/workflow-distributed.cjs.map +1 -1
  300. package/dist/workflow-distributed.d.cts +25 -15
  301. package/dist/workflow-distributed.d.cts.map +1 -1
  302. package/dist/workflow-distributed.d.ts +25 -15
  303. package/dist/workflow-distributed.d.ts.map +1 -1
  304. package/dist/workflow-distributed.js +5 -5
  305. package/dist/workflow-distributed.js.map +1 -1
  306. package/dist/workflow.cjs +24 -30
  307. package/dist/workflow.cjs.map +1 -1
  308. package/dist/workflow.d.cts +11 -6
  309. package/dist/workflow.d.cts.map +1 -1
  310. package/dist/workflow.d.ts +11 -6
  311. package/dist/workflow.d.ts.map +1 -1
  312. package/dist/workflow.js +24 -30
  313. package/dist/workflow.js.map +1 -1
  314. package/dist/yaml-config.d.cts +2 -3
  315. package/dist/yaml-config.d.cts.map +1 -1
  316. package/dist/yaml-config.d.ts +2 -3
  317. package/dist/yaml-config.d.ts.map +1 -1
  318. package/package.json +24 -16
  319. package/dist/attribute-redacting-processor-DtTS9xxh.d.cts.map +0 -1
  320. package/dist/attribute-redacting-processor-DtTS9xxh.d.ts.map +0 -1
  321. package/dist/canonical-log-line-processor-BcRuAdRk.d.ts.map +0 -1
  322. package/dist/canonical-log-line-processor-CcrDi6TO.cjs.map +0 -1
  323. package/dist/canonical-log-line-processor-FLezvFCB.js.map +0 -1
  324. package/dist/canonical-log-line-processor-xvjMgtpF.d.cts.map +0 -1
  325. package/dist/define-event-CreknLm3.d.ts.map +0 -1
  326. package/dist/define-event-HZRizPwz.d.cts.map +0 -1
  327. package/dist/event-BEm5IJ8U.js +0 -761
  328. package/dist/event-BEm5IJ8U.js.map +0 -1
  329. package/dist/event-rzA1X5h3.cjs +0 -778
  330. package/dist/event-rzA1X5h3.cjs.map +0 -1
  331. package/dist/event-subscriber-D1XLkPzi.d.cts.map +0 -1
  332. package/dist/event-subscriber-D1XLkPzi.d.ts.map +0 -1
  333. package/dist/event-testing-BqRnI0z4.d.cts.map +0 -1
  334. package/dist/event-testing-CfFs3to2.d.ts.map +0 -1
  335. package/dist/filtering-span-processor-B8R8B7Uk.d.cts.map +0 -1
  336. package/dist/filtering-span-processor-B8R8B7Uk.d.ts.map +0 -1
  337. package/dist/functional-CwsPyc4l.cjs +0 -1298
  338. package/dist/functional-CwsPyc4l.cjs.map +0 -1
  339. package/dist/functional-dAYhXQPA.js +0 -1248
  340. package/dist/functional-dAYhXQPA.js.map +0 -1
  341. package/dist/index-Ck06vlW2.d.ts.map +0 -1
  342. package/dist/index-eKuioqT1.d.cts.map +0 -1
  343. package/dist/init-B7u-DjxM.d.ts.map +0 -1
  344. package/dist/init-BvBB45-T.js +0 -1034
  345. package/dist/init-BvBB45-T.js.map +0 -1
  346. package/dist/init-BxJEJ9Tn.cjs +0 -1111
  347. package/dist/init-BxJEJ9Tn.cjs.map +0 -1
  348. package/dist/init-DSrRmVnz.d.cts.map +0 -1
  349. package/dist/logger-BauSUhUv.d.cts.map +0 -1
  350. package/dist/logger-BauSUhUv.d.ts.map +0 -1
  351. package/dist/metric-testing-DXdK3-Q3.d.ts.map +0 -1
  352. package/dist/metric-testing-MxvzChDp.d.cts.map +0 -1
  353. package/dist/operation-context-CKBoA4Qy.js +0 -59
  354. package/dist/operation-context-CKBoA4Qy.js.map +0 -1
  355. package/dist/operation-context-hzKbTKnt.cjs +0 -72
  356. package/dist/operation-context-hzKbTKnt.cjs.map +0 -1
  357. package/dist/sampling-CR0Va1VB.d.ts.map +0 -1
  358. package/dist/sampling-DfYhDJij.d.cts.map +0 -1
  359. package/dist/span-name-normalizer-8ZOGJuwv.d.cts.map +0 -1
  360. package/dist/span-name-normalizer-8ZOGJuwv.d.ts.map +0 -1
  361. package/dist/trace-context-Cijqoi6e.d.cts.map +0 -1
  362. package/dist/trace-context-Cijqoi6e.d.ts.map +0 -1
  363. package/dist/track-D7O7oIZa.js +0 -1115
  364. package/dist/track-D7O7oIZa.js.map +0 -1
  365. package/dist/track-eovhCJ-I.cjs +0 -1218
  366. package/dist/track-eovhCJ-I.cjs.map +0 -1
  367. package/skills/analyze-traces/SKILL.md +0 -180
  368. package/skills/autotel-core/SKILL.md +0 -159
  369. package/skills/autotel-events/SKILL.md +0 -84
  370. package/skills/autotel-frameworks/SKILL.md +0 -90
  371. package/skills/autotel-instrumentation/SKILL.md +0 -145
  372. package/skills/autotel-request-logging/SKILL.md +0 -94
  373. package/skills/autotel-structured-errors/SKILL.md +0 -125
  374. package/skills/build-audit-trails/SKILL.md +0 -460
  375. package/skills/build-audit-trails/references/audit-queries.md +0 -73
  376. package/skills/build-audit-trails/references/framework-wiring.md +0 -196
  377. package/skills/debug-missing-spans/SKILL.md +0 -250
  378. package/skills/migrate-to-autotel/SKILL.md +0 -269
  379. package/skills/review-otel-patterns/SKILL.md +0 -538
  380. package/skills/review-otel-patterns/references/code-review.md +0 -76
  381. package/skills/review-otel-patterns/references/processor-pipeline.md +0 -205
  382. package/skills/review-otel-patterns/references/structured-errors.md +0 -102
  383. package/skills/review-otel-patterns/references/wide-spans.md +0 -85
  384. package/skills/tune-sampling/SKILL.md +0 -215
@@ -1,460 +0,0 @@
1
- ---
2
- name: build-audit-trails
3
- description: >
4
- Build or review tamper-aware audit trails on top of OpenTelemetry spans
5
- using autotel and the autotel-audit package (`withAudit`,
6
- `setAuditAttributes`, `forceKeepAuditEvent`). Covers what counts as
7
- auditable, the audit-only span discipline, sampling bypass, HMAC and
8
- hash-chain signing with tamper detection, denial logging, redaction,
9
- retention, GDPR right-to-erasure via crypto-shredding, separation from
10
- operational telemetry, testing audit spans, backend-agnostic audit queries,
11
- a production-readiness checklist, and framework wiring (Next.js, Nuxt,
12
- Nitro, NestJS, Express, Fastify, Hono, Cloudflare Workers, AWS Lambda,
13
- standalone). Use it to design new audit trails or review existing ones for
14
- GDPR, HIPAA, SOC 2, PCI-DSS, ISO 27001, SOX, and GxP compliance.
15
- license: MIT
16
- ---
17
-
18
- # Build audit trails
19
-
20
- An _audit trail_ is a record of who did what to which resource, when, and whether it was permitted — durable, tamper-evident, and admissible. Operational telemetry (latency, errors, span shapes) is for engineers; audit trails are for compliance, security, and forensics. They overlap technically but differ on every other axis.
21
-
22
- autotel lets you express both with the same primitive — a span — but you should keep them on **separate processors** so an audit event never gets dropped by sampling, never gets redacted by a debug rule, and never goes to the same backend as your ops data.
23
-
24
- ## When to use
25
-
26
- - Implementing GDPR / HIPAA / SOC2 / PCI-DSS / ISO 27001 / GxP compliance
27
- - Adding "who did what" trails for admin actions, access reviews, payments
28
- - Recording authorization decisions (allow + deny)
29
- - Building immutable evidence for incident response
30
- - Reviewing an existing audit trail for compliance gaps (see "Review an existing audit trail")
31
-
32
- ## Quick reference
33
-
34
- | Situation | Use |
35
- | --------------------------------------------------- | -------------------------------------------------------- |
36
- | Wrap an action so success/failure is audited + kept | `withAudit(metadata, fn)` from `autotel-audit` |
37
- | Tag the active span with `audit.*` attributes only | `setAuditAttributes(metadata)` |
38
- | Make sure an audit span survives tail sampling | `forceKeepAuditEvent()` |
39
- | Record an authorization denial | `audit({ …, outcome: 'deny', reason })` (Step 1 helper) |
40
- | Full control / framework-agnostic span helper | hand-rolled `audit()` (Step 1) |
41
- | Keep audit data off ops dashboards | `FilteringSpanProcessor` split (Step 3) |
42
- | Prove a record was not altered | HMAC or hash-chain signature (Step 4) |
43
- | Honor a GDPR erasure request on an append-only log | crypto-shredding (Step 6.5) |
44
- | Assert the trail in tests | `createTraceCollector()` from `autotel/testing` (Step 8) |
45
-
46
- ## The shortest path: the `autotel-audit` package
47
-
48
- `autotel-audit` ships this discipline as helpers. Reach for these before hand-rolling:
49
-
50
- ```typescript
51
- import {
52
- withAudit,
53
- setAuditAttributes,
54
- forceKeepAuditEvent,
55
- } from 'autotel-audit';
56
-
57
- // Wrap the action: sets audit.* attributes, force-keeps past tail sampling,
58
- // and tags outcome 'success' / 'failure' automatically.
59
- await withAudit(
60
- {
61
- action: 'user.delete',
62
- resource: 'user',
63
- actorId: 'usr_42',
64
- category: 'admin',
65
- },
66
- async () => db.user.delete({ where: { id } }),
67
- );
68
-
69
- // Or tag the current span yourself and opt out of sampling:
70
- setAuditAttributes({
71
- action: 'secret.read',
72
- resource: 'sec_abc',
73
- actorId: 'usr_42',
74
- });
75
- forceKeepAuditEvent();
76
- ```
77
-
78
- `withAudit` marks the span with `autotel.audit = true` and sets the tail-sampling keep flags via `forceKeepAuditEvent`, so audit events are never dropped. The rest of this guide builds the same model from raw spans when you need full control over the schema, signing, and the pipeline split. If you use the package, filter on `autotel.audit` (not `audit`) in Step 3.
79
-
80
- ## The audit span discipline
81
-
82
- An auditable event has six required parts:
83
-
84
- | Field | OTel attribute | Example |
85
- | ------------------- | --------------------------------------------------------------- | --------------------------------------------- |
86
- | When | (span timestamp) | `2026-05-04T17:23:11.412Z` |
87
- | Who | `enduser.id` + `enduser.role` | `usr_42`, `admin` |
88
- | Where (acting from) | `client.address`, `network.peer.address`, `user_agent.original` | `203.0.113.5`, `Chrome 121` |
89
- | What | `audit.action` | `secret.read`, `policy.update`, `user.delete` |
90
- | Which resource | `audit.resource.type` + `audit.resource.id` | `secret`, `sec_abc` |
91
- | Outcome | `audit.outcome` (`allow` / `deny`) + `audit.reason` | `deny`, `MFA required` |
92
-
93
- Plus useful optional fields: `audit.policy.id` (which policy made the call), `audit.evidence` (linked artefact id), `audit.actor.session.id`.
94
-
95
- ## Step 1: Define a typed `audit()` helper
96
-
97
- Centralise the schema in one place so every site gets it right:
98
-
99
- ```typescript
100
- import { trace, SpanKind } from '@opentelemetry/api';
101
-
102
- type AuditAction =
103
- | 'secret.read'
104
- | 'secret.write'
105
- | 'secret.delete'
106
- | 'policy.update'
107
- | 'user.create'
108
- | 'user.delete'
109
- | 'data.export'
110
- | 'session.assume';
111
-
112
- interface AuditPayload {
113
- action: AuditAction;
114
- resource: { type: string; id: string };
115
- outcome: 'allow' | 'deny';
116
- reason?: string;
117
- actor?: { id: string; role?: string; sessionId?: string };
118
- policy?: { id: string };
119
- evidence?: { id: string };
120
- }
121
-
122
- const tracer = trace.getTracer('autotel-audit', '1.0.0');
123
-
124
- export function audit(payload: AuditPayload): void {
125
- const span = tracer.startSpan(`audit.${payload.action}`, {
126
- kind: SpanKind.INTERNAL,
127
- attributes: {
128
- audit: true,
129
- 'audit.action': payload.action,
130
- 'audit.outcome': payload.outcome,
131
- 'audit.resource.type': payload.resource.type,
132
- 'audit.resource.id': payload.resource.id,
133
- ...(payload.reason && { 'audit.reason': payload.reason }),
134
- ...(payload.actor?.id && { 'enduser.id': payload.actor.id }),
135
- ...(payload.actor?.role && { 'enduser.role': payload.actor.role }),
136
- ...(payload.actor?.sessionId && {
137
- 'audit.actor.session.id': payload.actor.sessionId,
138
- }),
139
- ...(payload.policy?.id && { 'audit.policy.id': payload.policy.id }),
140
- ...(payload.evidence?.id && { 'audit.evidence.id': payload.evidence.id }),
141
- },
142
- });
143
- span.end();
144
- }
145
- ```
146
-
147
- ## Step 2: Always log denials
148
-
149
- A frequent compliance failure is "we logged what users did but not what we **stopped** them doing." Wrap the authorization decision so both branches go through `audit()`:
150
-
151
- ```typescript
152
- export async function withAuthz<T>(
153
- payload: Omit<AuditPayload, 'outcome'>,
154
- decide: () => Promise<{ allow: boolean; reason?: string }>,
155
- body: () => Promise<T>,
156
- ): Promise<T> {
157
- const decision = await decide();
158
- if (!decision.allow) {
159
- audit({ ...payload, outcome: 'deny', reason: decision.reason });
160
- throw createStructuredError({
161
- status: 403,
162
- code: 'FORBIDDEN',
163
- message: 'Not allowed',
164
- why: decision.reason ?? 'Insufficient permissions',
165
- });
166
- }
167
- audit({ ...payload, outcome: 'allow' });
168
- return body();
169
- }
170
- ```
171
-
172
- ## Step 3: Separate the audit pipeline
173
-
174
- Critical: route audit spans to a **different processor and backend** so:
175
-
176
- - They are never dropped by head or tail sampling.
177
- - They are not subject to development-mode debug exporters.
178
- - They go to a write-once / append-only store (S3 Object Lock, immutable bucket, dedicated audit DB).
179
-
180
- How a span flows once you split the pipeline:
181
-
182
- ```text
183
- audit(payload)
184
- └─ span.attributes['audit'] = true (or autotel.audit via the package)
185
- │
186
- ├─► FilteringSpanProcessor include: audit === true ─► auditExporter ─► append-only store
187
- │
188
- └─► FilteringSpanProcessor exclude: audit === true ─► opsExporter (PII-redacted dashboards)
189
- ```
190
-
191
- ```typescript
192
- import {
193
- composeSpanProcessors,
194
- composeSubscribers,
195
- defineConfig,
196
- } from 'autotel-edge';
197
- import { BatchSpanProcessor, FilteringSpanProcessor } from 'autotel/processors';
198
-
199
- const auditExporter = new BatchSpanProcessor(
200
- new OTLPHttpJsonExporter({
201
- url: process.env.AUDIT_OTLP!,
202
- headers: { authorization: `Bearer ${process.env.AUDIT_TOKEN!}` },
203
- }),
204
- );
205
- const opsExporter = new BatchSpanProcessor(
206
- new OTLPHttpJsonExporter({ url: process.env.OPS_OTLP! }),
207
- );
208
-
209
- // Only audit spans reach the audit pipeline.
210
- const auditOnly = new FilteringSpanProcessor({
211
- include: (span) => span.attributes['audit'] === true,
212
- next: auditExporter,
213
- });
214
-
215
- // Conversely, ops never sees audit spans (avoid leaking PII to dashboards).
216
- const opsOnly = new FilteringSpanProcessor({
217
- exclude: (span) => span.attributes['audit'] === true,
218
- next: opsExporter,
219
- });
220
-
221
- export const otelConfig = defineConfig({
222
- service: { name: 'app' },
223
- spanProcessors: composeSpanProcessors([auditOnly, opsOnly]),
224
- });
225
- ```
226
-
227
- ## Step 4: Tamper detection
228
-
229
- For environments where audit storage is shared with the producing service (no append-only bucket), sign each span:
230
-
231
- ```typescript
232
- import { createHmac, randomUUID } from 'node:crypto'
233
-
234
- function signAuditAttributes(attrs: Record<string, unknown>): string {
235
- const key = process.env.AUDIT_HMAC_KEY!
236
- const payload = JSON.stringify(Object.fromEntries(Object.entries(attrs).sort()))
237
- return createHmac('sha256', key).update(payload).digest('hex')
238
- }
239
-
240
- export function audit(payload: AuditPayload): void {
241
- const id = randomUUID()
242
- const attributes = { /* … as before … */, 'audit.id': id }
243
- const signature = signAuditAttributes(attributes)
244
- attributes['audit.signature.alg'] = 'HMAC-SHA256'
245
- attributes['audit.signature.value'] = signature
246
- // … startSpan …
247
- }
248
- ```
249
-
250
- Verify on the read side: recompute the HMAC over the same sorted attribute set (excluding `audit.signature.value` itself); mismatched ⇒ tampered.
251
-
252
- For multi-tenant or extra-strict (HIPAA), use Ed25519 with per-environment keys and rotate.
253
-
254
- ## Step 5: Redaction — what stays and what goes
255
-
256
- | Field | In audit span? | Notes |
257
- | ------------------------ | -------------- | ------------------------------------------------------------------------------------- |
258
- | `enduser.id` | ✅ | Internal user id; never the email |
259
- | `audit.resource.id` | ✅ | Required for forensics |
260
- | `client.address` | ✅ | Last-octet redaction acceptable for IPv4 |
261
- | Free-form payload bodies | ❌ | Never inline raw input — link by id (`audit.evidence.id`) |
262
- | Secret values | ❌ | Use `audit.action=secret.read` + `audit.resource.id=sec_abc`, never the secret itself |
263
- | Authorization headers | ❌ | Token names ok (`bearer.*`), values never |
264
-
265
- `attributeRedactor` defaults are too aggressive for audit (you may need `enduser.id` literal, not masked). Disable redaction selectively:
266
-
267
- ```typescript
268
- spanProcessors: composeSpanProcessors([
269
- // No redactor on the audit branch — keys are already conservative
270
- auditOnly,
271
- // Strict redactor on ops
272
- new AttributeRedactingProcessor(opsOnly, { redactor: 'strict' }),
273
- ]);
274
- ```
275
-
276
- ## Step 6: Retention
277
-
278
- Audit retention is set by regulation, not engineering taste. Common minimums:
279
-
280
- | Regulation | Minimum retention |
281
- | -------------------- | -------------------------------------------- |
282
- | GDPR | 6 years (financial), 12 months (operational) |
283
- | HIPAA | 6 years |
284
- | PCI-DSS | 1 year (online), 3 months hot |
285
- | SOX | 7 years |
286
- | GxP / 21 CFR Part 11 | Lifetime of product + 10 years |
287
-
288
- Express retention as a backend lifecycle policy (S3 Object Lock COMPLIANCE mode, BigQuery `--time_partitioning_expiration`), not application code.
289
-
290
- ## Step 6.5: GDPR and the right to erasure
291
-
292
- An append-only audit log and GDPR Article 17 ("right to be forgotten") look like a contradiction: you must keep the audit record, but the subject can demand their personal data be erased. Resolve it with **crypto-shredding** rather than deleting rows.
293
-
294
- - Store the immutable facts in the clear: `audit.action`, `audit.outcome`, timestamps, `audit.resource.id`.
295
- - Encrypt any personal data (names, emails, free-form context) with a **per-subject key**, and store only the ciphertext on the span (or a reference to it).
296
- - Keep per-subject keys in a separate key store. To honor an erasure request, delete that subject's key. The audit record stays intact and tamper-evident; the personal fields become permanently unrecoverable.
297
-
298
- ```typescript
299
- // Never put raw PII on the span. Store a reference and shred the key on request.
300
- setAuditAttributes({
301
- action: 'profile.update',
302
- resource: 'user',
303
- actorId: 'usr_42',
304
- 'subject.id': 'usr_42', // internal id, safe to retain
305
- 'pii.ref': 'kms://subjects/usr_42/v3', // ciphertext lives off-span, keyed per subject
306
- });
307
- ```
308
-
309
- This keeps the chain of custody and signatures valid (you never mutate a signed record) while making erasure a key-management operation. Confirm the approach with your DPO; some regulators accept crypto-shredding as erasure, others want documented justification.
310
-
311
- ## Step 7: Framework wiring
312
-
313
- The handlers below are the common cases. For Nuxt, Nitro, NestJS, Fastify, AWS Lambda, and standalone jobs, see [references/framework-wiring.md](references/framework-wiring.md).
314
-
315
- ### Next.js
316
-
317
- ```typescript
318
- // app/admin/users/[id]/route.ts
319
- import { withAuthz, audit } from '@/lib/audit';
320
-
321
- export async function DELETE(
322
- req: Request,
323
- { params }: { params: { id: string } },
324
- ) {
325
- return withAuthz(
326
- {
327
- action: 'user.delete',
328
- resource: { type: 'user', id: params.id },
329
- actor: { id: req.headers.get('x-user-id')!, role: 'admin' },
330
- },
331
- async () => ({ allow: await canDelete(req, params.id) }),
332
- async () => {
333
- await db.user.delete({ where: { id: params.id } });
334
- return Response.json({ ok: true });
335
- },
336
- );
337
- }
338
- ```
339
-
340
- ### Hono
341
-
342
- ```typescript
343
- import { audit, withAuthz } from './audit';
344
- app.post('/secrets/:id/read', async (c) => {
345
- return withAuthz(
346
- {
347
- action: 'secret.read',
348
- resource: { type: 'secret', id: c.req.param('id') },
349
- actor: { id: c.var.user.id, role: c.var.user.role },
350
- },
351
- () => requireScope(c, 'secrets:read'),
352
- async () => c.json({ value: await secrets.read(c.req.param('id')) }),
353
- );
354
- });
355
- ```
356
-
357
- ### Cloudflare Workers
358
-
359
- `audit()` from inside `defineWorkerFetch` — `ctx.waitUntil` makes sure the audit span is exported before the response returns:
360
-
361
- ```typescript
362
- export default defineWorkerFetch(
363
- { service: { name: 'admin-api' } },
364
- async (request, env, ctx, log) => {
365
- return withAuthz(
366
- {
367
- action: 'data.export',
368
- resource: { type: 'project', id: 'p_123' },
369
- actor: { id: 'usr_42' },
370
- },
371
- async () => ({ allow: true }),
372
- async () => Response.json({ ok: true }),
373
- );
374
- },
375
- );
376
- ```
377
-
378
- ## Step 8: Test the trail
379
-
380
- An audit trail you have not tested is a compliance risk. The two tests that matter most: the denial path is recorded, and the audit attributes are present and correct. Use `createTraceCollector()` from `autotel/testing` to assert on emitted spans.
381
-
382
- ```typescript
383
- import { describe, it, expect, beforeEach } from 'vitest';
384
- import { createTraceCollector, type TraceCollector } from 'autotel/testing';
385
-
386
- describe('audit trail', () => {
387
- let collector: TraceCollector;
388
- beforeEach(() => {
389
- collector = createTraceCollector();
390
- });
391
-
392
- it('records a denial with reason and actor', async () => {
393
- await expect(deleteUser(forbiddenReq)).rejects.toMatchObject({
394
- status: 403,
395
- });
396
-
397
- const [span] = collector.getSpansByAttributes({ 'audit.outcome': 'deny' });
398
- expect(span).toBeDefined();
399
- expect(span.attributes['audit.action']).toBe('user.delete');
400
- expect(span.attributes['audit.reason']).toBeTruthy();
401
- expect(span.attributes['enduser.id']).toBe('usr_42');
402
- });
403
-
404
- it('records the success path on allow', async () => {
405
- await deleteUser(allowedReq);
406
- expect(
407
- collector.getSpansByAttributes({ 'audit.outcome': 'allow' }),
408
- ).toHaveLength(1);
409
- });
410
- });
411
- ```
412
-
413
- Test the signature too: build an audit span, recompute the HMAC over the sorted attributes, and assert it matches; then mutate one attribute and assert it no longer does.
414
-
415
- ## Review an existing audit trail
416
-
417
- When the task is to audit existing code rather than build new, work these four passes in order and report findings as you go.
418
-
419
- 1. **Pipeline.** Grep for where audit spans are produced (`audit(`, `withAudit`, `setAuditAttributes`). Confirm a `FilteringSpanProcessor` routes them to a separate, append-only backend, and that ops never receives them. Flag any audit span subject to sampling.
420
- 2. **Coverage.** List every `audit(`/`withAudit` call site. Are denials logged, not just successes? Are mutating admin actions, access reviews, payments, and data exports all covered? Flag audit-on-every-read noise.
421
- 3. **Integrity + redaction.** Is there a signature (HMAC or hash-chain) where storage is shared with the producer? Are raw payloads, secrets, or emails on the span instead of references and internal ids? Is the ops branch redacted?
422
- 4. **Tests + retention.** Is there a denial-path test and a signature-verification test? Is retention enforced at the storage layer (lifecycle policy), not in code?
423
-
424
- ## Production checklist
425
-
426
- - [ ] Audit spans marked (`audit` / `autotel.audit`) and force-kept past sampling
427
- - [ ] Separate processor and backend from ops; ops branch redacted
428
- - [ ] Both allow and deny outcomes recorded
429
- - [ ] No secrets, tokens, raw payloads, or emails on spans (references and internal ids only)
430
- - [ ] Signature (HMAC or hash-chain) where storage is shared with the producer; keys rotated
431
- - [ ] Retention set as a storage lifecycle policy per regulation
432
- - [ ] GDPR erasure plan (crypto-shredding) for personal fields
433
- - [ ] Multi-tenant isolation on the audit store
434
- - [ ] Denial-path and signature-verification tests in CI
435
-
436
- To query the trail (denials, per-actor history, tamper detection) across Honeycomb, Grafana Tempo, or Datadog, see [references/audit-queries.md](references/audit-queries.md).
437
-
438
- ## Anti-patterns
439
-
440
- | Anti-pattern | Fix |
441
- | ---------------------------------------------- | -------------------------------------------------------------- |
442
- | Audit logs in `console.log` / unstructured | Use `audit()` so every event has the same shape |
443
- | Same backend for audit and ops | Separate processors, separate retention |
444
- | Audit subject to sampling | `FilteringSpanProcessor` with `include: span.attributes.audit` |
445
- | Logging only successes | Always log denials too |
446
- | Putting secrets / payloads in audit attributes | Reference by id only (`audit.evidence.id`) |
447
- | No tamper detection | HMAC signature on critical environments |
448
- | Custom retention in code | Express via storage-layer lifecycle policy |
449
- | Audit on every read of harmless data | Audit _meaningful_ events; not every list call |
450
- | Audit row tied to a specific framework | The `audit()` function is framework-agnostic |
451
- | `enduser.id` = email | Use the internal id; emails go in a separate identity table |
452
-
453
- ## Glossary
454
-
455
- - **Audit span** — an OpenTelemetry span that records who did what to which resource, marked `audit` / `autotel.audit` so it is routed and retained separately from ops telemetry.
456
- - **Force-keep** — opting a span out of tail sampling so it is always exported; `forceKeepAuditEvent()` sets the autotel tail-keep flags.
457
- - **Denial** — an authorization decision that blocked an action; recorded with `audit.outcome = 'deny'` and a reason. Logging denials is as important as logging successes.
458
- - **Hash-chain** — linking each audit record to the hash of the previous one so removing or reordering records is detectable.
459
- - **Crypto-shredding** — satisfying an erasure request by destroying the per-subject encryption key rather than deleting the immutable record.
460
- - **Append-only store** — a backend that rejects updates and deletes (S3 Object Lock, immutable bucket, WORM storage), the destination for audit spans.
@@ -1,73 +0,0 @@
1
- # Querying the audit trail
2
-
3
- Because audit events are OpenTelemetry spans, you query them with the same tools as the rest of your telemetry, no separate audit UI required. The attribute names below match the skill: `audit.action`, `audit.outcome`, `audit.resource.id`, `enduser.id`, `autotel.audit`, and `audit.signature.value`.
4
-
5
- Run these against the **audit backend** (the append-only one), not your ops backend.
6
-
7
- ## Find all denials in a window
8
-
9
- A spike in denials is a security signal (credential stuffing, privilege probing).
10
-
11
- - **Honeycomb** — filter `autotel.audit = true` AND `audit.outcome = deny`, group by `audit.action` and `enduser.id`, visualize `COUNT`.
12
- - **Grafana Tempo (TraceQL)**:
13
- ```
14
- { span.autotel.audit = true && span.audit.outcome = "deny" }
15
- ```
16
- - **Datadog (spans search)**:
17
- ```
18
- @autotel.audit:true @audit.outcome:deny
19
- ```
20
-
21
- ## Trace one actor across every resource
22
-
23
- Answer "everything user X did" for an access review or incident.
24
-
25
- - **Honeycomb** — filter `enduser.id = "usr_42"`, group by `audit.action`, `audit.resource.type`, order by timestamp.
26
- - **TraceQL**:
27
- ```
28
- { span.enduser.id = "usr_42" && span.autotel.audit = true }
29
- ```
30
- - **Datadog**:
31
- ```
32
- @enduser.id:usr_42 @autotel.audit:true
33
- ```
34
-
35
- ## Who touched one resource
36
-
37
- Answer "everyone who accessed secret `sec_abc`".
38
-
39
- - **TraceQL**:
40
- ```
41
- { span.audit.resource.id = "sec_abc" && span.autotel.audit = true }
42
- ```
43
- - **Datadog**:
44
- ```
45
- @audit.resource.id:sec_abc @autotel.audit:true
46
- ```
47
-
48
- ## Spot coverage gaps
49
-
50
- Confirm sensitive actions are actually being recorded. Group audit spans by `audit.action` and compare against your list of auditable actions. An action that never appears is either never exercised or never audited; both deserve a look.
51
-
52
- - **Honeycomb** — group by `audit.action`, `COUNT`, over 30 days.
53
-
54
- ## Detect tampering or missing signatures
55
-
56
- In a shared-storage setup every audit span should carry `audit.signature.value`. Spans without one, or whose recomputed HMAC does not match, are suspect.
57
-
58
- - **Find unsigned audit spans (TraceQL)**:
59
- ```
60
- { span.autotel.audit = true && span.audit.signature.value = nil }
61
- ```
62
- - **Datadog**:
63
- ```
64
- @autotel.audit:true -@audit.signature.value:*
65
- ```
66
-
67
- Verification itself happens in code: export the spans, recompute the HMAC over the sorted attribute set (excluding `audit.signature.value`), and flag mismatches. A scheduled job that does this and writes its own audit span (`action: 'audit.integrity.check'`) gives you meta-auditing.
68
-
69
- ## Tips
70
-
71
- - Pin the time range explicitly; audit queries often span months, well past hot-storage windows.
72
- - Export results to CSV/NDJSON for auditors who need evidence outside the observability tool.
73
- - Keep these queries in version control next to the audit code so reviewers can reproduce them.