datex-studio-cli 0.4.16__tar.gz → 0.4.18__tar.gz

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 (215) hide show
  1. datex_studio_cli-0.4.18/CONTEXT.md +13 -0
  2. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/PKG-INFO +2 -1
  3. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/README.md +1 -0
  4. datex_studio_cli-0.4.18/otel/.env.example +14 -0
  5. datex_studio_cli-0.4.18/otel/Dockerfile +24 -0
  6. datex_studio_cli-0.4.18/otel/README.md +174 -0
  7. datex_studio_cli-0.4.18/otel/apply-local-cache.js +88 -0
  8. datex_studio_cli-0.4.18/otel/collector-config.yaml +145 -0
  9. datex_studio_cli-0.4.18/otel/docker-compose.yml +19 -0
  10. datex_studio_cli-0.4.18/otel/local-test-settings.json +26 -0
  11. datex_studio_cli-0.4.18/otel/remote-settings.json +36 -0
  12. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/pyproject.toml +1 -1
  13. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/__init__.py +1 -1
  14. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/auth.py +82 -19
  15. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/branch.py +18 -3
  16. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/cascade.py +9 -3
  17. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/configuration.py +49 -16
  18. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/datasource.py +47 -22
  19. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/devops.py +227 -2
  20. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/init.py +5 -1
  21. datex_studio_cli-0.4.18/src/dxs/commands/ng/api.py +334 -0
  22. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/ng/preview.py +259 -89
  23. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/batch.py +1 -1
  24. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/data.py +2 -2
  25. datex_studio_cli-0.4.18/src/dxs/commands/validation_report.py +122 -0
  26. datex_studio_cli-0.4.18/src/dxs/core/agent_browser.py +309 -0
  27. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/auth/datex_tenant.py +8 -10
  28. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/auth/tenants.py +18 -1
  29. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/datasource/flow_generator.py +116 -16
  30. datex_studio_cli-0.4.18/src/dxs/core/datasource/flow_shape.py +182 -0
  31. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/datasource/generator.py +13 -6
  32. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/datasource/models.py +97 -5
  33. datex_studio_cli-0.4.18/src/dxs/core/datasource/validator.py +259 -0
  34. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/devops/client.py +41 -0
  35. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/devops/helpers.py +56 -0
  36. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/devops/models.py +130 -0
  37. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/ng/mocks.py +9 -0
  38. datex_studio_cli-0.4.18/src/dxs/ng/serve_lock.py +99 -0
  39. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/models.py +4 -0
  40. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/preview_arjs.py +10 -153
  41. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/svg_renderer.py +6 -0
  42. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/paths.py +42 -0
  43. datex_studio_cli-0.4.16/src/dxs/commands/ng/api.py +0 -149
  44. datex_studio_cli-0.4.16/src/dxs/core/datasource/validator.py +0 -155
  45. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/.gitignore +0 -0
  46. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/report-creator.skill +0 -0
  47. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/scripts/analyze_corpus.py +0 -0
  48. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/scripts/generate_rdlx_schema.py +0 -0
  49. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/__main__.py +0 -0
  50. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/cli.py +0 -0
  51. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/__init__.py +0 -0
  52. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/api.py +0 -0
  53. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/config.py +0 -0
  54. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/crm.py +0 -0
  55. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/crm_delivery.py +0 -0
  56. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/crm_time.py +0 -0
  57. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/document.py +0 -0
  58. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/endpoint.py +0 -0
  59. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/env.py +0 -0
  60. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/explore.py +0 -0
  61. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/function.py +0 -0
  62. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/marketplace.py +0 -0
  63. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/ng/__init__.py +0 -0
  64. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/ng/_common.py +0 -0
  65. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/ng/create.py +0 -0
  66. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/ng/data.py +0 -0
  67. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/ng/pack.py +0 -0
  68. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/odata.py +0 -0
  69. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/organization.py +0 -0
  70. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/proxy.py +0 -0
  71. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/reference.py +0 -0
  72. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/release_notes.py +0 -0
  73. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/repo.py +0 -0
  74. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/__init__.py +0 -0
  75. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/add_cmds.py +0 -0
  76. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/api.py +0 -0
  77. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/create.py +0 -0
  78. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/dataset.py +0 -0
  79. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/edit.py +0 -0
  80. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/folder.py +0 -0
  81. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/preview.py +0 -0
  82. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/report/schema_cmds.py +0 -0
  83. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/reset.py +0 -0
  84. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/schema.py +0 -0
  85. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/servicepack.py +0 -0
  86. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/source.py +0 -0
  87. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/studio.py +0 -0
  88. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/telemetry.py +0 -0
  89. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/commands/user.py +0 -0
  90. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/context.py +0 -0
  91. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/__init__.py +0 -0
  92. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/api/__init__.py +0 -0
  93. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/api/app_config.py +0 -0
  94. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/api/client.py +0 -0
  95. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/api/endpoints.py +0 -0
  96. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/api/metadata_models.py +0 -0
  97. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/api/models.py +0 -0
  98. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/api/reference_graph.py +0 -0
  99. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/auth/__init__.py +0 -0
  100. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/auth/decorators.py +0 -0
  101. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/auth/msal_client.py +0 -0
  102. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/auth/token_cache.py +0 -0
  103. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/cache.py +0 -0
  104. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/datasource/__init__.py +0 -0
  105. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/datasource/flow_models.py +0 -0
  106. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/datasource/parsers.py +0 -0
  107. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/datasource/resolver.py +0 -0
  108. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/datasource/type_def_parser.py +0 -0
  109. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/designer/__init__.py +0 -0
  110. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/designer/flow_models.py +0 -0
  111. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/designer/models.py +0 -0
  112. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/designer/parsers.py +0 -0
  113. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/devops/__init__.py +0 -0
  114. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/dynamics/__init__.py +0 -0
  115. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/dynamics/client.py +0 -0
  116. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/dynamics/html.py +0 -0
  117. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/dynamics/metadata_cache.py +0 -0
  118. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/dynamics/resolvers.py +0 -0
  119. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/dynamics/time_entry.py +0 -0
  120. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/footprint/__init__.py +0 -0
  121. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/footprint/client.py +0 -0
  122. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/footprint/edmx_parser.py +0 -0
  123. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/footprint/metadata.py +0 -0
  124. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/function/__init__.py +0 -0
  125. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/function/generator.py +0 -0
  126. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/function/models.py +0 -0
  127. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/function/validator.py +0 -0
  128. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/graph.py +0 -0
  129. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/onboarding.py +0 -0
  130. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/output/__init__.py +0 -0
  131. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/output/csv_fmt.py +0 -0
  132. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/output/formatter.py +0 -0
  133. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/output/json_fmt.py +0 -0
  134. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/output/redaction.py +0 -0
  135. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/output/yaml_fmt.py +0 -0
  136. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/release_notes.py +0 -0
  137. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/responses.py +0 -0
  138. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/telemetry/__init__.py +0 -0
  139. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/telemetry/config.py +0 -0
  140. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/telemetry/identity.py +0 -0
  141. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/telemetry/recorder.py +0 -0
  142. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/telemetry/scrubber.py +0 -0
  143. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/core/telemetry/sender.py +0 -0
  144. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/models/__init__.py +0 -0
  145. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/ng/__init__.py +0 -0
  146. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/ng/folder.py +0 -0
  147. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/ng/manifest.py +0 -0
  148. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/ng/preview.py +0 -0
  149. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/ng/scaffold.py +0 -0
  150. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/py.typed +0 -0
  151. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/__init__.py +0 -0
  152. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/datasource_binding.py +0 -0
  153. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/engine.py +0 -0
  154. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/field_parser.py +0 -0
  155. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/folder.py +0 -0
  156. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/manifest.py +0 -0
  157. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/preview.py +0 -0
  158. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/schema.py +0 -0
  159. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/templates/__init__.py +0 -0
  160. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/templates/bill_of_lading.rdlx-json +0 -0
  161. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/templates/shipping_label.rdlx-json +0 -0
  162. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/validate_arjs.py +0 -0
  163. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/validator.py +0 -0
  164. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/report/wrapper.py +0 -0
  165. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/__init__.py +0 -0
  166. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/click_options.py +0 -0
  167. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/clipboard.py +0 -0
  168. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/config.py +0 -0
  169. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/errors.py +0 -0
  170. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/filtering.py +0 -0
  171. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/image.py +0 -0
  172. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/resolvers.py +0 -0
  173. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/responses.py +0 -0
  174. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/restricted.py +0 -0
  175. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/sorting.py +0 -0
  176. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/update_check.py +0 -0
  177. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/utils/versioning.py +0 -0
  178. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/__init__.py +0 -0
  179. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/app.py +0 -0
  180. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/design.py +0 -0
  181. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/proxy_app.py +0 -0
  182. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/404/index.html +0 -0
  183. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/404.html +0 -0
  184. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT/_buildManifest.js +0 -0
  185. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT/_ssgManifest.js +0 -0
  186. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/0b24cca5-c1e1c8810348f107.js +0 -0
  187. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/255-102f2e5b2e3dc2ef.js +0 -0
  188. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +0 -0
  189. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/538-84e2e111415f1fda.js +0 -0
  190. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/697-0e000ab410d9f470.js +0 -0
  191. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/871-1acacdb7b4022abf.js +0 -0
  192. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/8b8f67fc-6295949a4b5485a4.js +0 -0
  193. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/909-c88abba3cf0caec3.js +0 -0
  194. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/app/_not-found/page-ea1be7001c230704.js +0 -0
  195. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/app/design/capture/page-a5e129c2d223432c.js +0 -0
  196. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/app/design/page-21ba66a3dd3b03f0.js +0 -0
  197. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/app/layout-2cc6eac09e476c91.js +0 -0
  198. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/app/page-20c358395882cdac.js +0 -0
  199. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/framework-de98b93a850cfc71.js +0 -0
  200. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/main-0f18f91200dac003.js +0 -0
  201. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/main-app-b69998d8941231d8.js +0 -0
  202. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/pages/_app-7d307437aca18ad4.js +0 -0
  203. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +0 -0
  204. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
  205. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/chunks/webpack-2b297ada5306c17f.js +0 -0
  206. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/_next/static/css/360c657de5e04df8.css +0 -0
  207. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/design/capture/index.html +0 -0
  208. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/design/capture/index.txt +0 -0
  209. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/design/index.html +0 -0
  210. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/design/index.txt +0 -0
  211. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/index.html +0 -0
  212. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/index.txt +0 -0
  213. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/render-cli.js +0 -0
  214. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/report-preview.html +0 -0
  215. {datex_studio_cli-0.4.16 → datex_studio_cli-0.4.18}/src/dxs/web/static/report-validate.html +0 -0
@@ -0,0 +1,13 @@
1
+ # Datex Studio CLI
2
+
3
+ The command-line interface (`dxs`) through which LLM agents and humans work with the Datex Studio low-code platform, plus the client side of its server counterpart, Quartermaster.
4
+
5
+ ## Language
6
+
7
+ **Quartermaster**:
8
+ The Datex-owned service that is the dxs CLI's server-side counterpart — it issues supplies (skills, context) and keeps the records (telemetry, config index).
9
+ _Avoid_: companion service, dxs backend, dxs service
10
+
11
+ **Endpoint family**:
12
+ A cohesive group of Quartermaster endpoints serving one CLI capability (telemetry ingest, feedback, skills distribution, OData proxy, config indexing, context store). The unit in which Quartermaster is composed, enabled, and — when one earns it — deployed separately.
13
+ _Avoid_: module, microservice, subsystem
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: datex-studio-cli
3
- Version: 0.4.16
3
+ Version: 0.4.18
4
4
  Summary: CLI for Datex Studio low-code platform, designed for LLM-based AI agents
5
5
  Project-URL: Homepage, https://github.com/datex/datex-studio-cli
6
6
  Project-URL: Documentation, https://github.com/datex/datex-studio-cli
@@ -761,6 +761,7 @@ dxs api PUT /some/endpoint '{"data": "value"}'
761
761
  ### For Human Users
762
762
 
763
763
  - **[Analysis Workflow](docs/analysis-workflow.md)** - Bulk analysis workflow documentation
764
+ - **[Claude Code Telemetry Collector](otel/README.md)** - Team-wide Claude Code observability: OTel collector → Datadog, rolled out from the claude.ai admin console
764
765
 
765
766
  ## Development
766
767
 
@@ -708,6 +708,7 @@ dxs api PUT /some/endpoint '{"data": "value"}'
708
708
  ### For Human Users
709
709
 
710
710
  - **[Analysis Workflow](docs/analysis-workflow.md)** - Bulk analysis workflow documentation
711
+ - **[Claude Code Telemetry Collector](otel/README.md)** - Team-wide Claude Code observability: OTel collector → Datadog, rolled out from the claude.ai admin console
711
712
 
712
713
  ## Development
713
714
 
@@ -0,0 +1,14 @@
1
+ # Copy to .env and fill in. .env is gitignored -- never commit the real key.
2
+ #
3
+ # Datadog ingest API key (Organization Settings > API Keys).
4
+ DD_API_KEY=your-datadog-api-key-here
5
+
6
+ # Datadog site for your org. The Datex org is US1 - East, which is datadoghq.com.
7
+ # DatexCorp is US3 - West, which would be us3.datadoghq.com.
8
+ DD_SITE=datadoghq.com
9
+
10
+ # Bearer token Claude Code clients must present (their
11
+ # OTEL_EXPORTER_OTLP_HEADERS must carry the same value). The default below
12
+ # matches local-test-settings.json for local runs; for Azure generate a strong
13
+ # secret (e.g. `openssl rand -hex 32`) and store it as a container secret.
14
+ OTLP_BEARER_TOKEN=local-dev-token
@@ -0,0 +1,24 @@
1
+ # OpenTelemetry Collector for Claude Code telemetry -> Datadog.
2
+ #
3
+ # The Datadog exporter lives only in the "contrib" distribution, not the core
4
+ # collector image.
5
+ #
6
+ # NOTE: pin this tag to a tested version (or a digest) before deploying to
7
+ # Azure. `latest` is fine for local verification, not for the team.
8
+ #
9
+ # Registry is fully qualified: podman does not default to Docker Hub for
10
+ # unqualified names, so a bare `otel/...` prompts or fails there.
11
+ FROM docker.io/otel/opentelemetry-collector-contrib:latest
12
+
13
+ # Copied to an explicit path so the config location never depends on the
14
+ # image's default, which differs between distributions. chown to the image's
15
+ # built-in non-root user so readability never depends on checkout file modes.
16
+ COPY --chown=10001:10001 collector-config.yaml /etc/otel/config.yaml
17
+
18
+ # 4318: OTLP http/protobuf (all Claude Code speaks).
19
+ # 13133: health_check extension, for orchestrator liveness/readiness probes.
20
+ EXPOSE 4318 13133
21
+
22
+ # DD_API_KEY, DD_SITE and OTLP_BEARER_TOKEN are supplied at runtime, never
23
+ # baked into the image.
24
+ CMD ["--config=/etc/otel/config.yaml"]
@@ -0,0 +1,174 @@
1
+ # Claude Code telemetry → Datadog
2
+
3
+ Centralised Claude Code observability for the team: an OpenTelemetry Collector holds the
4
+ Datadog credential, developer machines hold none, and configuration is pushed from the
5
+ claude.ai admin console rather than set up per-laptop.
6
+
7
+ ```
8
+ Claude Code (each dev) --OTLP/http--> Collector (Azure) --datadog exporter--> Datadog
9
+ ^ ^
10
+ | |
11
+ server-managed settings DD_API_KEY lives only here
12
+ (claude.ai admin console)
13
+ ```
14
+
15
+ ## Files
16
+
17
+ | File | Purpose |
18
+ |---|---|
19
+ | `Dockerfile` | Collector image (contrib distribution — the Datadog exporter is not in core) |
20
+ | `collector-config.yaml` | Receivers, processors, Datadog exporter for logs + traces + metrics |
21
+ | `docker-compose.yml` | Local verification harness |
22
+ | `.env.example` | Template for `DD_API_KEY` / `DD_SITE` / `OTLP_BEARER_TOKEN` — copy to `.env` (gitignored) |
23
+ | `remote-settings.json` | Payload for the claude.ai admin console |
24
+ | `local-test-settings.json` | Same env block pointed at `localhost` for local testing |
25
+ | `apply-local-cache.js` | Loads `local-test-settings.json` into Claude Code's settings cache for a local test run |
26
+
27
+ ## Verify locally
28
+
29
+ ```bash
30
+ cd otel
31
+ cp .env.example .env # fill in DD_API_KEY
32
+ docker compose up --build
33
+ ```
34
+
35
+ Then load the settings and restart:
36
+
37
+ ```bash
38
+ node apply-local-cache.js # writes ~/.claude/remote-settings.json, checks the collector
39
+ # --revert restores it to {}
40
+ ```
41
+
42
+ **Restart Claude Code immediately afterwards.** Two reasons: OpenTelemetry configuration is
43
+ only read at startup, and Claude Code refetches server-managed settings in the background —
44
+ when the org has no server-side config that refetch overwrites the cache with `{}`. A
45
+ hand-placed payload therefore survives exactly one session and must be re-applied before
46
+ each restart. Approve the `OTEL_EXPORTER_OTLP_ENDPOINT` dialog on startup or Claude Code
47
+ exits.
48
+
49
+ This one-session-per-edit friction disappears once the payload is delivered from the admin
50
+ console for real.
51
+
52
+ Confirm in Datadog under **Logs** (not APM) with `service:claude-code`. Collector-side, the
53
+ `debug` exporter prints per-batch item **counts** to container stdout — enough to confirm
54
+ data is flowing. It deliberately does not print payloads; see the verbosity note in
55
+ `collector-config.yaml` before raising it:
56
+
57
+ ```bash
58
+ docker compose logs -f otel-collector
59
+ ```
60
+
61
+ ## Hand off to the team
62
+
63
+ 1. **Decide the data-governance posture first** (see the Data governance section below):
64
+ keep or drop `OTEL_LOG_TOOL_CONTENT` in `remote-settings.json` *before* anything ships.
65
+ Raw API bodies (`OTEL_LOG_RAW_API_BODIES`) are already off; prompts, responses and tool
66
+ content still land in Datadog.
67
+ 2. Pin the base image in `Dockerfile` to a tested tag or digest — it currently says
68
+ `latest`. Then build and push to ACR, deploy as an Azure Container App or App Service.
69
+ Give the container an explicit memory limit and set `GOMEMLIMIT` to ~80% of it — the
70
+ `memory_limiter` processor depends on a real limit (`docker-compose.yml` shows the
71
+ pattern). Point liveness/readiness probes at the `health_check` extension on port 13133.
72
+ 3. Terminate TLS in front of it. **OTLP payloads carry full prompts, file contents and
73
+ responses** — this must not travel over plain HTTP. The endpoint pushed to clients is
74
+ the TLS front-end URL (Azure Container Apps ingress listens on 443), not `:4318` —
75
+ ingress targets the collector's internal 4318.
76
+ 4. Set `DD_API_KEY`, `DD_SITE` and `OTLP_BEARER_TOKEN` as container secrets, not image
77
+ layers. Generate the token with e.g. `openssl rand -hex 32`.
78
+ 5. Restrict ingress to corporate network / VPN. The bearer token the receiver now requires
79
+ is defense in depth on top of that — a shared, developer-visible secret, not a
80
+ substitute for network restriction.
81
+ 6. An Owner pastes `remote-settings.json` into
82
+ **claude.ai → Admin Settings → Claude Code → Managed settings**, replacing
83
+ `<COLLECTOR-PUBLIC-URL>` and `<OTLP-BEARER-TOKEN>`.
84
+
85
+ Each developer sees a **one-time approval dialog** for the endpoint variable. If they
86
+ decline, Claude Code exits. This is unavoidable — Claude Code always prompts for a
87
+ non-empty `OTEL_EXPORTER_OTLP_ENDPOINT`.
88
+
89
+ ## Where prompts and responses land
90
+
91
+ Verified against Claude Code 2.1.220 through this collector. **Both prompts and response
92
+ text are captured.**
93
+
94
+ | Content | Attribute | Event |
95
+ |---|---|---|
96
+ | Prompt text | `prompt_text` | `user_prompt` |
97
+ | Prompt uuid | `prompt.id` | all events |
98
+ | Assistant response text | `response`, `response_length` | `assistant_response` |
99
+ | Tool calls / inputs | `tool_input`, `tool_parameters` | `tool_result` |
100
+ | Cost / tokens | `cost_usd`, `input_tokens`, `output_tokens` | `api_request` |
101
+ | Thinking | `content[].thinking` | always `<REDACTED>` |
102
+
103
+ ### Why the collector is required, not just convenient
104
+
105
+ Sending straight to Datadog's OTLP intake (`https://otlp.datadoghq.com`) loses data. Two
106
+ separate defects, both fixed here:
107
+
108
+ **1. Prompt text destroyed by an attribute collision.** Claude Code emits `prompt` (the
109
+ text) *and* `prompt.id` (a uuid). Datadog flattens dotted keys into nested objects, so
110
+ `prompt.id` becomes an object at `prompt` and the sibling string is silently discarded —
111
+ `prompt_length` still reports the real size, which is how we caught it. The `transform`
112
+ processor in `collector-config.yaml` copies the string to `prompt_text` and drops the
113
+ colliding key.
114
+
115
+ Slash-command prompts were never affected, because command dispatches carry no `prompt.id`
116
+ and therefore no collision. That asymmetry — "prompt text only shows up for slash
117
+ commands" — is the signature of this bug.
118
+
119
+ **2. `assistant_response` events dropped in transit.** With the direct endpoint these never
120
+ arrived, across hours of querying. Through the collector they arrive with a populated
121
+ `response` attribute. Same flags, same client version — the only change was the endpoint,
122
+ so Datadog's OTLP intake appears to drop them. The collector's `datadog` exporter forwards
123
+ them intact.
124
+
125
+ ### Query gotchas
126
+
127
+ - **`prompt_length` without `prompt_text`** means the transform isn't running — that is the
128
+ collision, not redaction.
129
+ - **Search by attribute, not free text.** `@marker:VALUE` works; a bare string only matches
130
+ the log message body, which is usually just the event name.
131
+ - **No `api_request_body` / `api_response_body` events** — `OTEL_LOG_RAW_API_BODIES` is
132
+ deliberately off: request bodies repeat the whole conversation on every API call (pure
133
+ ingest cost, plus one more copy of any secret in context), and `user_prompt` +
134
+ `assistant_response` + the tool events already reconstruct the transcript. If raw bodies
135
+ are ever needed, re-enable the flag in `remote-settings.json` and note request bodies
136
+ arrive truncated at the 60 KB `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH` limit (invalid
137
+ JSON — filter on `body_truncated`).
138
+
139
+ A `Stop` hook reading `last_assistant_message` is **not needed**. That was a workaround
140
+ built before `assistant_response` was confirmed working through the collector. An
141
+ implementation is kept at `~/.claude/hooks/dd-transcript.js` (Delian's machine,
142
+ unregistered) but is not part of this setup.
143
+
144
+ ## Enforcement reality check
145
+
146
+ Server-managed settings are, per Anthropic's docs, "a client-side control, not a security
147
+ boundary. On unmanaged devices, a user doesn't need admin or sudo access to bypass them."
148
+
149
+ | Bypass | Effect |
150
+ |---|---|
151
+ | Delete `~/.claude/remote-settings.json` | Brief unenforced window at next start |
152
+ | Run an older Claude Code | Never fetches managed settings |
153
+ | Set `ANTHROPIC_BASE_URL` or `CLAUDE_CODE_USE_BEDROCK` | Settings fetch skipped entirely |
154
+
155
+ `forceRemoteSettingsRefresh` and `requiredMinimumVersion` (both already in
156
+ `remote-settings.json`) close the easy gaps. For genuine enforcement, deploy
157
+ endpoint-managed settings by MDM to `C:\Program Files\ClaudeCode\managed-settings.json`
158
+ — note that `C:\ProgramData\ClaudeCode\` stopped being read in v2.1.75.
159
+
160
+ **Server-managed and endpoint-managed settings do not merge.** If server-managed delivers
161
+ any keys at all, the MDM file is ignored completely. Pick one as the source of truth.
162
+
163
+ ## Data governance
164
+
165
+ With these flags on, Datadog receives prompts, responses, and tool inputs and outputs —
166
+ including the contents of any file Claude Code reads. In `datex-application-api` that means
167
+ connection strings and `Azure__ClientSecret` can land in Datadog logs. Every event also
168
+ carries the developer's email and account UUIDs. (Raw API bodies —
169
+ `OTEL_LOG_RAW_API_BODIES` — are deliberately off: they would re-send the whole conversation
170
+ on every API call for no analytical gain.)
171
+
172
+ Decide deliberately whether that is acceptable before rolling out, and consider dropping
173
+ `OTEL_LOG_TOOL_CONTENT` if it is not. Datadog's Sensitive Data Scanner can redact patterns
174
+ at ingest as a second layer.
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Local testing helper.
4
+ *
5
+ * Copies local-test-settings.json into Claude Code's server-managed settings
6
+ * cache (~/.claude/remote-settings.json), simulating a policy pushed from the
7
+ * admin console.
8
+ *
9
+ * Why this is needed: Claude Code applies the cache at startup, then refetches
10
+ * from Anthropic in the background. When the org has no server-managed config,
11
+ * that refetch overwrites the cache with {} -- so a hand-placed payload is good
12
+ * for exactly one session and must be re-applied before each restart.
13
+ *
14
+ * Usage: node apply-local-cache.js [--revert]
15
+ *
16
+ * Restart Claude Code IMMEDIATELY after running this. OpenTelemetry settings
17
+ * are only read at startup, and the background fetch will blank the file.
18
+ */
19
+
20
+ const fs = require('fs');
21
+ const path = require('path');
22
+ const http = require('http');
23
+
24
+ const HOME = process.env.USERPROFILE || process.env.HOME;
25
+ const CACHE = path.join(HOME, '.claude', 'remote-settings.json');
26
+ const SOURCE = path.join(__dirname, 'local-test-settings.json');
27
+
28
+ if (process.argv.includes('--revert')) {
29
+ fs.writeFileSync(CACHE, '{}\n');
30
+ console.log(`reverted ${CACHE} to {}`);
31
+ process.exit(0);
32
+ }
33
+
34
+ const source = JSON.parse(fs.readFileSync(SOURCE, 'utf8'));
35
+
36
+ // Drop the _comment-style documentation keys; they would be stripped by
37
+ // Claude Code's schema validation anyway.
38
+ const payload = Object.fromEntries(Object.entries(source).filter(([k]) => !k.startsWith('_')));
39
+
40
+ if (!payload.env || !Object.keys(payload.env).length) {
41
+ console.error(`no env block found in ${SOURCE}`);
42
+ process.exit(1);
43
+ }
44
+
45
+ fs.writeFileSync(CACHE, JSON.stringify(payload, null, 2) + '\n');
46
+ console.log(`wrote ${Object.keys(payload.env).length} env vars to ${CACHE}`);
47
+
48
+ const endpoint = payload.env.OTEL_EXPORTER_OTLP_ENDPOINT || '';
49
+ console.log(`endpoint: ${endpoint}`);
50
+
51
+ // Check the collector is actually listening -- restarting into a dead endpoint
52
+ // wastes a whole session, since the payload only survives one startup.
53
+ const m = endpoint.match(/^http:\/\/([^:/]+):(\d+)/);
54
+ if (!m) {
55
+ console.log('\nendpoint is not local http; skipping reachability check');
56
+ return finish();
57
+ }
58
+
59
+ // Send the same auth header the client will use, so the probe exercises the
60
+ // collector's bearertokenauth too. 401 = token mismatch, not unreachable.
61
+ const headers = { 'Content-Type': 'application/json' };
62
+ for (const pair of (payload.env.OTEL_EXPORTER_OTLP_HEADERS || '').split(',')) {
63
+ const i = pair.indexOf('=');
64
+ if (i > 0) headers[pair.slice(0, i).trim()] = pair.slice(i + 1).trim();
65
+ }
66
+
67
+ const req = http.request(
68
+ { method: 'POST', hostname: m[1], port: Number(m[2]), path: '/v1/logs', headers, timeout: 4000 },
69
+ (res) => {
70
+ res.resume();
71
+ console.log(res.statusCode === 401
72
+ ? 'collector: reachable but rejected the bearer token (HTTP 401) -- OTEL_EXPORTER_OTLP_HEADERS must match the collector OTLP_BEARER_TOKEN'
73
+ : `collector: reachable (HTTP ${res.statusCode})`);
74
+ finish();
75
+ }
76
+ );
77
+ req.on('error', (e) => {
78
+ console.log(`collector: NOT reachable (${e.code})`);
79
+ console.log(' start it first: podman start datex-otel-collector');
80
+ finish();
81
+ });
82
+ req.on('timeout', () => { req.destroy(); console.log('collector: timeout'); finish(); });
83
+ req.end('{}');
84
+
85
+ function finish() {
86
+ console.log('\nRestart Claude Code now -- the background fetch will blank this file.');
87
+ console.log('Approve the OTEL_EXPORTER_OTLP_ENDPOINT dialog on startup, or Claude Code exits.');
88
+ }
@@ -0,0 +1,145 @@
1
+ # OpenTelemetry Collector configuration for Claude Code telemetry -> Datadog.
2
+ #
3
+ # Claude Code clients send OTLP over http/protobuf to this collector; the
4
+ # collector holds the only copy of the Datadog API key. Developer machines
5
+ # never see a credential.
6
+
7
+ extensions:
8
+ # Liveness/readiness endpoint for orchestrator probes (Azure Container Apps)
9
+ # and local checks: GET http://localhost:13133/health
10
+ health_check:
11
+ endpoint: 0.0.0.0:13133
12
+
13
+ # Clients must present this token (pushed to them as OTEL_EXPORTER_OTLP_HEADERS
14
+ # in the same settings payload). Defense in depth on top of network/ingress
15
+ # restriction -- the receiver is the sole write path into the Datadog org.
16
+ bearertokenauth:
17
+ scheme: Bearer
18
+ token: ${env:OTLP_BEARER_TOKEN}
19
+
20
+ receivers:
21
+ # http/protobuf only -- it is all Claude Code speaks. No gRPC listener:
22
+ # an unused port on this receiver is pure attack surface.
23
+ otlp:
24
+ protocols:
25
+ http:
26
+ endpoint: 0.0.0.0:4318
27
+ auth:
28
+ authenticator: bearertokenauth
29
+
30
+ processors:
31
+ # First in every pipeline: refuse new data instead of dying when memory runs
32
+ # hot. Percentages are relative to the container memory limit -- always run
33
+ # this image with an explicit limit and GOMEMLIMIT at ~80% of it
34
+ # (docker-compose.yml shows the pattern for local).
35
+ memory_limiter:
36
+ check_interval: 1s
37
+ limit_percentage: 80
38
+ spike_limit_percentage: 25
39
+
40
+ # Claude Code sends no hostname, which makes Datadog tag every span
41
+ # issue_type:empty_hostname. Detecting it here fixes grouping.
42
+ #
43
+ # CAVEAT: this reports the COLLECTOR's hostname, not the developer's. With a
44
+ # single shared collector every developer's telemetry carries the same
45
+ # host.name. Group per developer by user.email or session.id instead. Drop
46
+ # this processor if host-level grouping matters more than filling the field.
47
+ resource_detection:
48
+ detectors: [env, system]
49
+ system:
50
+ hostname_sources: [os]
51
+
52
+ # Claude Code sends BOTH `prompt` (the prompt text) and `prompt.id` (a uuid).
53
+ # Datadog flattens dotted keys into nested objects, so `prompt.id` becomes an
54
+ # object at `prompt` and silently discards the sibling string -- the prompt
55
+ # text vanishes while `prompt_length` still reports its real size.
56
+ #
57
+ # Renaming the string before export sidesteps the collision. Slash-command
58
+ # prompts were unaffected because command dispatches carry no `prompt.id`,
59
+ # which is why prompt text only ever showed up for them.
60
+ transform:
61
+ error_mode: ignore
62
+ log_statements:
63
+ - context: log
64
+ statements:
65
+ - set(attributes["prompt_text"], attributes["prompt"]) where IsString(attributes["prompt"])
66
+ - delete_key(attributes, "prompt") where attributes["prompt_text"] != nil
67
+ # The traces beta puts prompt/tool content on spans and span events
68
+ # (OTEL_LOG_TOOL_CONTENT). If those carry the same prompt + prompt.id pair,
69
+ # the identical flattening collision recurs in Datadog APM. Precautionary
70
+ # mirror -- verify against a live trace; drop if spans never carry `prompt`.
71
+ trace_statements:
72
+ - context: span
73
+ statements:
74
+ - set(attributes["prompt_text"], attributes["prompt"]) where IsString(attributes["prompt"])
75
+ - delete_key(attributes, "prompt") where attributes["prompt_text"] != nil
76
+ - context: spanevent
77
+ statements:
78
+ - set(attributes["prompt_text"], attributes["prompt"]) where IsString(attributes["prompt"])
79
+ - delete_key(attributes, "prompt") where attributes["prompt_text"] != nil
80
+
81
+ # Sized to Datadog's documented example for this exporter. Batch limits count
82
+ # ITEMS, not bytes -- content-bearing events run up to 60 KB each, and
83
+ # oversized batches can exceed Datadog's ~5 MB uncompressed logs intake cap.
84
+ batch:
85
+ send_batch_size: 10
86
+ send_batch_max_size: 100
87
+ timeout: 10s
88
+
89
+ exporters:
90
+ datadog:
91
+ api:
92
+ key: ${env:DD_API_KEY}
93
+ site: ${env:DD_SITE}
94
+ # In-memory queue only -- diskless by choice. Failure behavior:
95
+ # - retries never give up on elapsed time (max_elapsed_time: 0), so a
96
+ # Datadog outage of any length is survived as long as the queue holds
97
+ # (permanent 4xx errors are still dropped, not retried -- a bad API key
98
+ # can't jam the queue)
99
+ # - the queue absorbs outages/bursts; memory_limiter stops intake before
100
+ # queue growth can OOM the container
101
+ # - when the queue IS full, new data drops and
102
+ # otelcol_exporter_enqueue_failed_* counts it -- alert on that metric
103
+ # - a container restart loses whatever is queued; accepted cost of
104
+ # staying diskless
105
+ retry_on_failure:
106
+ enabled: true
107
+ initial_interval: 5s
108
+ max_interval: 60s
109
+ max_elapsed_time: 0
110
+ sending_queue:
111
+ enabled: true
112
+ num_consumers: 10
113
+ queue_size: 5000
114
+
115
+ # Wired into every pipeline so container logs confirm data is arriving.
116
+ #
117
+ # verbosity: basic logs per-batch item COUNTS only. Do not raise this to
118
+ # detailed outside short local debugging -- detailed writes full payloads to
119
+ # container stdout, and those payloads contain prompts, responses and the
120
+ # contents of any file Claude Code read.
121
+ debug:
122
+ verbosity: basic
123
+
124
+ service:
125
+ extensions: [health_check, bearertokenauth]
126
+
127
+ pipelines:
128
+ logs:
129
+ receivers: [otlp]
130
+ processors: [memory_limiter, resource_detection, transform, batch]
131
+ exporters: [datadog, debug]
132
+
133
+ traces:
134
+ receivers: [otlp]
135
+ processors: [memory_limiter, resource_detection, transform, batch]
136
+ exporters: [datadog, debug]
137
+
138
+ metrics:
139
+ receivers: [otlp]
140
+ processors: [memory_limiter, resource_detection, batch]
141
+ exporters: [datadog, debug]
142
+
143
+ telemetry:
144
+ logs:
145
+ level: info
@@ -0,0 +1,19 @@
1
+ # Local verification harness. Azure deployment uses the image directly.
2
+ services:
3
+ otel-collector:
4
+ build: .
5
+ image: datex-claude-otel-collector:local
6
+ container_name: datex-otel-collector
7
+ env_file:
8
+ - .env
9
+ environment:
10
+ # ~80% of mem_limit, so Go's GC cooperates with the memory_limiter
11
+ # processor instead of the kernel OOM-killing the container.
12
+ GOMEMLIMIT: 400MiB
13
+ ports:
14
+ # Loopback only: the receiver is a write path into the org's Datadog
15
+ # account -- don't expose it to every peer on the office/VPN network.
16
+ - "127.0.0.1:4318:4318"
17
+ - "127.0.0.1:13133:13133"
18
+ mem_limit: 512m
19
+ restart: unless-stopped
@@ -0,0 +1,26 @@
1
+ {
2
+ "_comment": "Local verification only. Merge this env block into your own ~/.claude/settings.json while testing the collector on localhost, then remove it once server-managed settings are live. Same keys as remote-settings.json except OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS (local-dev token, matching .env.example) and deployment.environment. Again no Datadog key -- the collector holds it.",
3
+
4
+ "env": {
5
+ "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
6
+ "CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
7
+
8
+ "OTEL_LOGS_EXPORTER": "otlp",
9
+ "OTEL_TRACES_EXPORTER": "otlp",
10
+ "OTEL_METRICS_EXPORTER": "otlp",
11
+ "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
12
+ "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318",
13
+ "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer local-dev-token",
14
+
15
+ "OTEL_METRIC_EXPORT_INTERVAL": "60000",
16
+ "OTEL_METRICS_INCLUDE_SESSION_ID": "true",
17
+
18
+ "OTEL_SERVICE_NAME": "claude-code",
19
+ "OTEL_RESOURCE_ATTRIBUTES": "deployment.environment=local,service.version=1.0",
20
+
21
+ "OTEL_LOG_USER_PROMPTS": "1",
22
+ "OTEL_LOG_ASSISTANT_RESPONSES": "1",
23
+ "OTEL_LOG_TOOL_DETAILS": "1",
24
+ "OTEL_LOG_TOOL_CONTENT": "1"
25
+ }
26
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "_comment": "Paste the contents of this file (minus the _comment keys) into claude.ai > Admin Settings > Claude Code > Managed settings. Requires Owner or Primary Owner role and a Claude for Teams/Enterprise plan. The only secret here is the shared collector bearer token; the Datadog API key lives only on the collector.",
3
+
4
+ "_endpoint_note": "Replace <COLLECTOR-PUBLIC-URL> with the collector's public TLS URL (e.g. https://otel.example.com). That is the TLS front end -- Azure Container Apps ingress listens on 443 -- NOT the collector's internal port 4318, which ingress targets. Must be HTTPS in production: OTLP payloads carry full prompts and responses. Claude Code always shows each developer a one-time approval dialog for a non-empty OTEL_EXPORTER_OTLP_ENDPOINT; if they decline, Claude Code exits.",
5
+
6
+ "_auth_note": "Replace <OTLP-BEARER-TOKEN> with the token configured on the collector (its OTLP_BEARER_TOKEN secret). It is a shared, developer-visible secret: defense in depth on top of ingress restriction, not a substitute for it.",
7
+
8
+ "env": {
9
+ "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
10
+ "CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
11
+
12
+ "OTEL_LOGS_EXPORTER": "otlp",
13
+ "OTEL_TRACES_EXPORTER": "otlp",
14
+ "OTEL_METRICS_EXPORTER": "otlp",
15
+ "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
16
+ "OTEL_EXPORTER_OTLP_ENDPOINT": "https://<COLLECTOR-PUBLIC-URL>",
17
+ "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer <OTLP-BEARER-TOKEN>",
18
+
19
+ "OTEL_METRIC_EXPORT_INTERVAL": "60000",
20
+ "OTEL_METRICS_INCLUDE_SESSION_ID": "true",
21
+
22
+ "OTEL_SERVICE_NAME": "claude-code",
23
+ "OTEL_RESOURCE_ATTRIBUTES": "deployment.environment=dev,service.version=1.0",
24
+
25
+ "OTEL_LOG_USER_PROMPTS": "1",
26
+ "OTEL_LOG_ASSISTANT_RESPONSES": "1",
27
+ "OTEL_LOG_TOOL_DETAILS": "1",
28
+ "OTEL_LOG_TOOL_CONTENT": "1"
29
+ },
30
+
31
+ "_metrics_note": "Metrics use Claude Code's default delta temporality (what Datadog expects) and the default-off app.version attribute. session.id is kept on metrics for session-level drill-down -- an accepted Datadog custom-metric cardinality cost, since every session mints new timeseries; set it to false if the custom-metrics bill grows. Per-developer analysis uses user.email either way.",
32
+
33
+ "_enforcement_note": "forceRemoteSettingsRefresh makes the CLI exit rather than run unenforced when the settings fetch fails. requiredMinimumVersion stops developers dropping to a build that ignores server-managed settings (NOTE: this key is not in Anthropic's public docs -- confirm it is honored, or it may be silently stripped). Neither makes this a security boundary -- see README.",
34
+ "forceRemoteSettingsRefresh": true,
35
+ "requiredMinimumVersion": "2.1.220"
36
+ }
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "datex-studio-cli"
7
- version = "0.4.16"
7
+ version = "0.4.18"
8
8
  description = "CLI for Datex Studio low-code platform, designed for LLM-based AI agents"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,4 +1,4 @@
1
1
  """Datex Studio CLI - Command-line interface for Datex Studio platform."""
2
2
 
3
- __version__ = "0.4.16"
3
+ __version__ = "0.4.18"
4
4
  __app_name__ = "dxs"