@voxgig/sdkgen 4.32.1 → 4.33.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 (411) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/helpers/naming.js +1 -1
  3. package/dist/helpers/naming.js.map +1 -1
  4. package/dist/tsconfig.tsbuildinfo +1 -1
  5. package/model/sdkgen.aontu +7 -1
  6. package/package.json +1 -1
  7. package/project/.sdk/model/feature/debug.aontu +3 -1
  8. package/project/.sdk/src/cmp/c/PrepareAuth_c.ts +8 -28
  9. package/project/.sdk/src/cmp/c/TestClean_c.ts +774 -0
  10. package/project/.sdk/src/cmp/c/Test_c.ts +3 -0
  11. package/project/.sdk/src/cmp/c/fragment/Entity.fragment.c +16 -5
  12. package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +1 -1
  13. package/project/.sdk/src/cmp/clojure/PrepareAuth_clojure.ts +3 -0
  14. package/project/.sdk/src/cmp/clojure/TestClean_clojure.ts +473 -0
  15. package/project/.sdk/src/cmp/clojure/Test_clojure.ts +6 -0
  16. package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +18 -8
  17. package/project/.sdk/src/cmp/cpp/PrepareAuth_cpp.ts +3 -0
  18. package/project/.sdk/src/cmp/cpp/TestClean_cpp.ts +782 -0
  19. package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +1 -1
  20. package/project/.sdk/src/cmp/cpp/Test_cpp.ts +2 -0
  21. package/project/.sdk/src/cmp/csharp/PrepareAuth_csharp.ts +3 -0
  22. package/project/.sdk/src/cmp/csharp/TestClean_csharp.ts +887 -0
  23. package/project/.sdk/src/cmp/csharp/Test_csharp.ts +2 -0
  24. package/project/.sdk/src/cmp/csharp/fragment/EntityBase.fragment.cs +68 -4
  25. package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +8 -2
  26. package/project/.sdk/src/cmp/csharp/fragment/SdkError.fragment.cs +49 -0
  27. package/project/.sdk/src/cmp/elixir/PrepareAuth_elixir.ts +3 -0
  28. package/project/.sdk/src/cmp/elixir/Schema_elixir.ts +20 -10
  29. package/project/.sdk/src/cmp/elixir/TestClean_elixir.ts +666 -0
  30. package/project/.sdk/src/cmp/elixir/Test_elixir.ts +4 -0
  31. package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +1 -1
  32. package/project/.sdk/src/cmp/elixir/fragment/Pipeline.fragment.ex +14 -2
  33. package/project/.sdk/src/cmp/go/PrepareAuth_go.ts +3 -0
  34. package/project/.sdk/src/cmp/go/TestClean_go.ts +804 -0
  35. package/project/.sdk/src/cmp/go/Test_go.ts +3 -0
  36. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +54 -4
  37. package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +27 -2
  38. package/project/.sdk/src/cmp/java/PrepareAuth_java.ts +3 -0
  39. package/project/.sdk/src/cmp/java/TestClean_java.ts +884 -0
  40. package/project/.sdk/src/cmp/java/Test_java.ts +2 -0
  41. package/project/.sdk/src/cmp/java/fragment/EntityBase.fragment.java +56 -11
  42. package/project/.sdk/src/cmp/java/fragment/SdkError.fragment.java +36 -3
  43. package/project/.sdk/src/cmp/js/PrepareAuth_js.ts +3 -0
  44. package/project/.sdk/src/cmp/js/TestClean_js.ts +458 -0
  45. package/project/.sdk/src/cmp/js/Test_js.ts +2 -0
  46. package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +5 -4
  47. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +7 -1
  48. package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +7 -1
  49. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +7 -1
  50. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +7 -1
  51. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +7 -1
  52. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +11 -2
  53. package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +17 -1
  54. package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +5 -0
  55. package/project/.sdk/src/cmp/kotlin/PrepareAuth_kotlin.ts +3 -0
  56. package/project/.sdk/src/cmp/kotlin/TestClean_kotlin.ts +654 -0
  57. package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +3 -0
  58. package/project/.sdk/src/cmp/kotlin/fragment/EntityBase.fragment.kt +44 -11
  59. package/project/.sdk/src/cmp/kotlin/fragment/SdkError.fragment.kt +31 -0
  60. package/project/.sdk/src/cmp/lua/PrepareAuth_lua.ts +3 -0
  61. package/project/.sdk/src/cmp/lua/TestClean_lua.ts +769 -0
  62. package/project/.sdk/src/cmp/lua/Test_lua.ts +3 -0
  63. package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +77 -1
  64. package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +49 -2
  65. package/project/.sdk/src/cmp/ocaml/Entity_ocaml.ts +3 -2
  66. package/project/.sdk/src/cmp/ocaml/PrepareAuth_ocaml.ts +4 -25
  67. package/project/.sdk/src/cmp/ocaml/TestClean_ocaml.ts +538 -0
  68. package/project/.sdk/src/cmp/ocaml/Test_ocaml.ts +5 -0
  69. package/project/.sdk/src/cmp/ocaml/fragment/RunOp.fragment.ml +16 -4
  70. package/project/.sdk/src/cmp/perl/PrepareAuth_perl.ts +3 -0
  71. package/project/.sdk/src/cmp/perl/TestClean_perl.ts +619 -0
  72. package/project/.sdk/src/cmp/perl/Test_perl.ts +3 -0
  73. package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +67 -5
  74. package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +13 -1
  75. package/project/.sdk/src/cmp/php/PrepareAuth_php.ts +3 -0
  76. package/project/.sdk/src/cmp/php/TestClean_php.ts +809 -0
  77. package/project/.sdk/src/cmp/php/Test_php.ts +2 -0
  78. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +96 -55
  79. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +15 -2
  80. package/project/.sdk/src/cmp/py/PrepareAuth_py.ts +3 -0
  81. package/project/.sdk/src/cmp/py/TestClean_py.ts +549 -0
  82. package/project/.sdk/src/cmp/py/Test_py.ts +3 -0
  83. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +83 -55
  84. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +19 -3
  85. package/project/.sdk/src/cmp/rb/PrepareAuth_rb.ts +3 -0
  86. package/project/.sdk/src/cmp/rb/TestClean_rb.ts +535 -0
  87. package/project/.sdk/src/cmp/rb/Test_rb.ts +3 -0
  88. package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +108 -46
  89. package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +12 -1
  90. package/project/.sdk/src/cmp/rust/PrepareAuth_rust.ts +9 -45
  91. package/project/.sdk/src/cmp/rust/TestClean_rust.ts +881 -0
  92. package/project/.sdk/src/cmp/rust/Test_rust.ts +3 -0
  93. package/project/.sdk/src/cmp/rust/fragment/Entity.fragment.rs +14 -6
  94. package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +17 -1
  95. package/project/.sdk/src/cmp/rust/fragment/SdkError.fragment.rs +34 -2
  96. package/project/.sdk/src/cmp/scala/PrepareAuth_scala.ts +3 -0
  97. package/project/.sdk/src/cmp/scala/TestClean_scala.ts +608 -0
  98. package/project/.sdk/src/cmp/scala/Test_scala.ts +3 -0
  99. package/project/.sdk/src/cmp/scala/fragment/EntityBase.fragment.scala +58 -6
  100. package/project/.sdk/src/cmp/swift/PrepareAuth_swift.ts +3 -0
  101. package/project/.sdk/src/cmp/swift/TestClean_swift.ts +671 -0
  102. package/project/.sdk/src/cmp/swift/Test_swift.ts +3 -0
  103. package/project/.sdk/src/cmp/swift/fragment/EntityBase.fragment.swift +10 -0
  104. package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +16 -2
  105. package/project/.sdk/src/cmp/swift/fragment/SdkError.fragment.swift +47 -3
  106. package/project/.sdk/src/cmp/ts/PrepareAuth_ts.ts +3 -0
  107. package/project/.sdk/src/cmp/ts/TestClean_ts.ts +465 -0
  108. package/project/.sdk/src/cmp/ts/Test_ts.ts +2 -0
  109. package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +5 -4
  110. package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +7 -1
  111. package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +7 -1
  112. package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +7 -1
  113. package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +7 -1
  114. package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +7 -1
  115. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +8 -2
  116. package/project/.sdk/src/cmp/ts/fragment/SdkError.fragment.ts +20 -2
  117. package/project/.sdk/src/cmp/zig/PrepareAuth_zig.ts +3 -0
  118. package/project/.sdk/src/cmp/zig/TestClean_zig.ts +791 -0
  119. package/project/.sdk/src/cmp/zig/Test_zig.ts +5 -0
  120. package/project/.sdk/src/cmp/zig/fragment/Build.fragment.zig +19 -0
  121. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +14 -5
  122. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +1 -1
  123. package/project/.sdk/tm/c/core/context.c +25 -0
  124. package/project/.sdk/tm/c/core/error.c +16 -0
  125. package/project/.sdk/tm/c/core/sdk.h +22 -0
  126. package/project/.sdk/tm/c/feature/audit.c +2 -0
  127. package/project/.sdk/tm/c/feature/cost.c +1 -0
  128. package/project/.sdk/tm/c/feature/debug.c +19 -29
  129. package/project/.sdk/tm/c/feature/log.c +21 -2
  130. package/project/.sdk/tm/c/feature/proxy.c +55 -3
  131. package/project/.sdk/tm/c/feature/secrets.c +7 -0
  132. package/project/.sdk/tm/c/feature/telemetry.c +2 -0
  133. package/project/.sdk/tm/c/tests/feature_test.c +2 -2
  134. package/project/.sdk/tm/c/utility/clean.c +530 -8
  135. package/project/.sdk/tm/c/utility/done.c +28 -12
  136. package/project/.sdk/tm/c/utility/make_error.c +4 -3
  137. package/project/.sdk/tm/c/utility/make_options.c +71 -45
  138. package/project/.sdk/tm/clojure/feature/secrets/sdk/feature/secrets.clj +15 -0
  139. package/project/.sdk/tm/clojure/src/sdk/client.clj +20 -4
  140. package/project/.sdk/tm/clojure/src/sdk/core.clj +319 -35
  141. package/project/.sdk/tm/clojure/src/sdk/features.clj +68 -30
  142. package/project/.sdk/tm/clojure/test/sdk/test/feature.clj +4 -2
  143. package/project/.sdk/tm/clojure/test/sdk/test/pipeline.clj +47 -20
  144. package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +4 -0
  145. package/project/.sdk/tm/cpp/core/types.hpp +93 -3
  146. package/project/.sdk/tm/cpp/feature/audit.hpp +1 -0
  147. package/project/.sdk/tm/cpp/feature/cost.hpp +1 -0
  148. package/project/.sdk/tm/cpp/feature/debug.hpp +20 -12
  149. package/project/.sdk/tm/cpp/feature/log.hpp +31 -9
  150. package/project/.sdk/tm/cpp/feature/proxy.hpp +52 -6
  151. package/project/.sdk/tm/cpp/feature/secrets.hpp +13 -0
  152. package/project/.sdk/tm/cpp/feature/telemetry.hpp +4 -2
  153. package/project/.sdk/tm/cpp/test/feature_test.cpp +2 -2
  154. package/project/.sdk/tm/cpp/utility/pipeline.hpp +426 -51
  155. package/project/.sdk/tm/csharp/core/Context.cs +32 -0
  156. package/project/.sdk/tm/csharp/core/Utility.cs +2 -0
  157. package/project/.sdk/tm/csharp/feature/AuditFeature.cs +1 -0
  158. package/project/.sdk/tm/csharp/feature/CostFeature.cs +7 -5
  159. package/project/.sdk/tm/csharp/feature/DebugFeature.cs +19 -16
  160. package/project/.sdk/tm/csharp/feature/FeatureOptions.cs +16 -0
  161. package/project/.sdk/tm/csharp/feature/LogFeature.cs +4 -1
  162. package/project/.sdk/tm/csharp/feature/ProxyFeature.cs +26 -5
  163. package/project/.sdk/tm/csharp/feature/SecretsFeature.cs +16 -0
  164. package/project/.sdk/tm/csharp/feature/TelemetryFeature.cs +4 -2
  165. package/project/.sdk/tm/csharp/test/FeatureTest.cs +2 -2
  166. package/project/.sdk/tm/csharp/utility/Clean.cs +440 -2
  167. package/project/.sdk/tm/csharp/utility/Done.cs +27 -11
  168. package/project/.sdk/tm/csharp/utility/MakeError.cs +19 -8
  169. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +119 -29
  170. package/project/.sdk/tm/csharp/utility/MakeResponse.cs +21 -11
  171. package/project/.sdk/tm/csharp/utility/Register.cs +1 -0
  172. package/project/.sdk/tm/elixir/lib/projectname/context.ex +19 -0
  173. package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +22 -1
  174. package/project/.sdk/tm/elixir/lib/projectname/error.ex +24 -0
  175. package/project/.sdk/tm/elixir/lib/projectname/feature/audit.ex +2 -2
  176. package/project/.sdk/tm/elixir/lib/projectname/feature/cost.ex +2 -2
  177. package/project/.sdk/tm/elixir/lib/projectname/feature/debug.ex +13 -13
  178. package/project/.sdk/tm/elixir/lib/projectname/feature/log.ex +18 -5
  179. package/project/.sdk/tm/elixir/lib/projectname/feature/proxy.ex +19 -1
  180. package/project/.sdk/tm/elixir/lib/projectname/feature/secrets.ex +15 -0
  181. package/project/.sdk/tm/elixir/lib/projectname/feature/telemetry.ex +4 -2
  182. package/project/.sdk/tm/elixir/lib/projectname/feature.ex +22 -0
  183. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +464 -41
  184. package/project/.sdk/tm/elixir/test/feature_test.exs +3 -2
  185. package/project/.sdk/tm/go/core/context.go +42 -0
  186. package/project/.sdk/tm/go/core/error.go +30 -10
  187. package/project/.sdk/tm/go/core/utility_type.go +2 -0
  188. package/project/.sdk/tm/go/feature/audit_feature.go +1 -0
  189. package/project/.sdk/tm/go/feature/base_feature.go +12 -0
  190. package/project/.sdk/tm/go/feature/cost_feature.go +2 -2
  191. package/project/.sdk/tm/go/feature/debug_feature.go +14 -12
  192. package/project/.sdk/tm/go/feature/log_feature.go +13 -8
  193. package/project/.sdk/tm/go/feature/proxy_feature.go +26 -6
  194. package/project/.sdk/tm/go/feature/secrets_feature.go +19 -0
  195. package/project/.sdk/tm/go/feature/telemetry_feature.go +4 -2
  196. package/project/.sdk/tm/go/test/feature_test.go +2 -2
  197. package/project/.sdk/tm/go/utility/clean.go +585 -2
  198. package/project/.sdk/tm/go/utility/done.go +29 -9
  199. package/project/.sdk/tm/go/utility/make_error.go +51 -16
  200. package/project/.sdk/tm/go/utility/make_options.go +77 -36
  201. package/project/.sdk/tm/go/utility/register.go +12 -0
  202. package/project/.sdk/tm/java/core/Context.java +29 -0
  203. package/project/.sdk/tm/java/core/SdkClient.java +4 -2
  204. package/project/.sdk/tm/java/core/Utility.java +7 -0
  205. package/project/.sdk/tm/java/feature/AuditFeature.java +6 -0
  206. package/project/.sdk/tm/java/feature/CostFeature.java +5 -0
  207. package/project/.sdk/tm/java/feature/DebugFeature.java +25 -14
  208. package/project/.sdk/tm/java/feature/LogFeature.java +11 -4
  209. package/project/.sdk/tm/java/feature/ProxyFeature.java +41 -6
  210. package/project/.sdk/tm/java/feature/SecretsFeature.java +18 -0
  211. package/project/.sdk/tm/java/feature/TelemetryFeature.java +8 -2
  212. package/project/.sdk/tm/java/test/FeatureTest.java +2 -2
  213. package/project/.sdk/tm/java/utility/Clean.java +519 -1
  214. package/project/.sdk/tm/java/utility/Done.java +1 -1
  215. package/project/.sdk/tm/java/utility/MakeError.java +5 -1
  216. package/project/.sdk/tm/java/utility/MakeOptions.java +55 -31
  217. package/project/.sdk/tm/java/utility/Register.java +4 -0
  218. package/project/.sdk/tm/js/src/Context.js +5 -1
  219. package/project/.sdk/tm/js/src/feature/audit/AuditFeature.js +2 -2
  220. package/project/.sdk/tm/js/src/feature/cost/CostFeature.js +2 -2
  221. package/project/.sdk/tm/js/src/feature/debug/DebugFeature.js +13 -7
  222. package/project/.sdk/tm/js/src/feature/log/LogFeature.js +9 -5
  223. package/project/.sdk/tm/js/src/feature/proxy/ProxyFeature.js +19 -1
  224. package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +14 -0
  225. package/project/.sdk/tm/js/src/feature/telemetry/TelemetryFeature.js +4 -2
  226. package/project/.sdk/tm/js/src/utility/CleanUtility.js +294 -21
  227. package/project/.sdk/tm/js/src/utility/DoneUtility.js +17 -5
  228. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +18 -2
  229. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -15
  230. package/project/.sdk/tm/js/src/utility/Utility.js +4 -2
  231. package/project/.sdk/tm/js/test/feature/harness.js +11 -1
  232. package/project/.sdk/tm/js/test/feature.test.js +9 -2
  233. package/project/.sdk/tm/kotlin/core/Context.kt +19 -0
  234. package/project/.sdk/tm/kotlin/core/SdkClient.kt +9 -2
  235. package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
  236. package/project/.sdk/tm/kotlin/feature/AuditFeature.kt +11 -9
  237. package/project/.sdk/tm/kotlin/feature/CostFeature.kt +8 -5
  238. package/project/.sdk/tm/kotlin/feature/DebugFeature.kt +15 -22
  239. package/project/.sdk/tm/kotlin/feature/LogFeature.kt +8 -4
  240. package/project/.sdk/tm/kotlin/feature/ProxyFeature.kt +26 -2
  241. package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +11 -0
  242. package/project/.sdk/tm/kotlin/feature/TelemetryFeature.kt +4 -2
  243. package/project/.sdk/tm/kotlin/test/FeatureTest.kt +2 -2
  244. package/project/.sdk/tm/kotlin/utility/CoreUtil.kt +447 -11
  245. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +38 -31
  246. package/project/.sdk/tm/kotlin/utility/Register.kt +1 -0
  247. package/project/.sdk/tm/lua/core/context.lua +43 -0
  248. package/project/.sdk/tm/lua/core/error.lua +36 -1
  249. package/project/.sdk/tm/lua/core/utility_type.lua +4 -0
  250. package/project/.sdk/tm/lua/feature/audit_feature.lua +2 -2
  251. package/project/.sdk/tm/lua/feature/cost_feature.lua +2 -2
  252. package/project/.sdk/tm/lua/feature/debug_feature.lua +21 -17
  253. package/project/.sdk/tm/lua/feature/log_feature.lua +2 -1
  254. package/project/.sdk/tm/lua/feature/proxy_feature.lua +23 -1
  255. package/project/.sdk/tm/lua/feature/secrets_feature.lua +18 -0
  256. package/project/.sdk/tm/lua/feature/telemetry_feature.lua +4 -2
  257. package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +3 -2
  258. package/project/.sdk/tm/lua/test/feature_test.lua +10 -3
  259. package/project/.sdk/tm/lua/utility/clean.lua +426 -2
  260. package/project/.sdk/tm/lua/utility/clean_explain.lua +34 -0
  261. package/project/.sdk/tm/lua/utility/done.lua +1 -7
  262. package/project/.sdk/tm/lua/utility/make_error.lua +3 -1
  263. package/project/.sdk/tm/lua/utility/make_options.lua +76 -30
  264. package/project/.sdk/tm/lua/utility/register.lua +4 -1
  265. package/project/.sdk/tm/ocaml/Makefile +5 -1
  266. package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +12 -1
  267. package/project/.sdk/tm/ocaml/sdk_features.ml +78 -18
  268. package/project/.sdk/tm/ocaml/sdk_helpers.ml +27 -0
  269. package/project/.sdk/tm/ocaml/sdk_runtime.ml +304 -26
  270. package/project/.sdk/tm/ocaml/sdk_types.ml +1 -0
  271. package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +3 -1
  272. package/project/.sdk/tm/ocaml/test/t_feature.ml +2 -2
  273. package/project/.sdk/tm/perl/core/context.pm +27 -0
  274. package/project/.sdk/tm/perl/core/error.pm +52 -5
  275. package/project/.sdk/tm/perl/feature/audit_feature.pm +2 -2
  276. package/project/.sdk/tm/perl/feature/cost_feature.pm +2 -2
  277. package/project/.sdk/tm/perl/feature/debug_feature.pm +17 -13
  278. package/project/.sdk/tm/perl/feature/log_feature.pm +3 -1
  279. package/project/.sdk/tm/perl/feature/proxy_feature.pm +21 -1
  280. package/project/.sdk/tm/perl/feature/secrets_feature.pm +20 -1
  281. package/project/.sdk/tm/perl/feature/telemetry_feature.pm +4 -2
  282. package/project/.sdk/tm/perl/t/feature.t +4 -2
  283. package/project/.sdk/tm/perl/utility/clean.pm +345 -1
  284. package/project/.sdk/tm/perl/utility/done.pm +24 -6
  285. package/project/.sdk/tm/perl/utility/make_error.pm +17 -4
  286. package/project/.sdk/tm/perl/utility/make_options.pm +33 -14
  287. package/project/.sdk/tm/php/core/Context.php +24 -1
  288. package/project/.sdk/tm/php/core/Error.php +34 -3
  289. package/project/.sdk/tm/php/core/UtilityType.php +4 -0
  290. package/project/.sdk/tm/php/feature/AuditFeature.php +2 -2
  291. package/project/.sdk/tm/php/feature/CostFeature.php +2 -2
  292. package/project/.sdk/tm/php/feature/DebugFeature.php +18 -9
  293. package/project/.sdk/tm/php/feature/LogFeature.php +5 -2
  294. package/project/.sdk/tm/php/feature/ProxyFeature.php +20 -1
  295. package/project/.sdk/tm/php/feature/SecretsFeature.php +18 -0
  296. package/project/.sdk/tm/php/feature/TelemetryFeature.php +4 -2
  297. package/project/.sdk/tm/php/test/FeatureTest.php +2 -2
  298. package/project/.sdk/tm/php/utility/Clean.php +438 -2
  299. package/project/.sdk/tm/php/utility/Done.php +14 -7
  300. package/project/.sdk/tm/php/utility/MakeError.php +9 -7
  301. package/project/.sdk/tm/php/utility/MakeOptions.php +62 -38
  302. package/project/.sdk/tm/php/utility/Register.php +2 -0
  303. package/project/.sdk/tm/py/pkg/core/context.py +17 -0
  304. package/project/.sdk/tm/py/pkg/core/error.py +42 -1
  305. package/project/.sdk/tm/py/pkg/core/utility_type.py +4 -0
  306. package/project/.sdk/tm/py/pkg/feature/audit_feature.py +2 -2
  307. package/project/.sdk/tm/py/pkg/feature/cost_feature.py +2 -2
  308. package/project/.sdk/tm/py/pkg/feature/debug_feature.py +17 -12
  309. package/project/.sdk/tm/py/pkg/feature/log_feature.py +2 -1
  310. package/project/.sdk/tm/py/pkg/feature/proxy_feature.py +18 -1
  311. package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +12 -0
  312. package/project/.sdk/tm/py/pkg/feature/telemetry_feature.py +4 -2
  313. package/project/.sdk/tm/py/pkg/utility/clean.py +311 -1
  314. package/project/.sdk/tm/py/pkg/utility/done.py +18 -5
  315. package/project/.sdk/tm/py/pkg/utility/make_error.py +9 -6
  316. package/project/.sdk/tm/py/pkg/utility/make_options.py +64 -25
  317. package/project/.sdk/tm/py/pkg/utility/make_response.py +19 -13
  318. package/project/.sdk/tm/py/pkg/utility/register.py +4 -2
  319. package/project/.sdk/tm/py/test/feature_harness.py +4 -0
  320. package/project/.sdk/tm/py/test/test_feature.py +2 -2
  321. package/project/.sdk/tm/py/test/test_primary_utility.py +1 -0
  322. package/project/.sdk/tm/rb/core/context.rb +28 -0
  323. package/project/.sdk/tm/rb/core/error.rb +30 -0
  324. package/project/.sdk/tm/rb/core/utility_type.rb +1 -1
  325. package/project/.sdk/tm/rb/feature/audit_feature.rb +2 -2
  326. package/project/.sdk/tm/rb/feature/cost_feature.rb +2 -2
  327. package/project/.sdk/tm/rb/feature/debug_feature.rb +15 -12
  328. package/project/.sdk/tm/rb/feature/log_feature.rb +3 -1
  329. package/project/.sdk/tm/rb/feature/proxy_feature.rb +25 -1
  330. package/project/.sdk/tm/rb/feature/secrets_feature.rb +17 -0
  331. package/project/.sdk/tm/rb/feature/telemetry_feature.rb +4 -2
  332. package/project/.sdk/tm/rb/test/feature_test.rb +4 -2
  333. package/project/.sdk/tm/rb/utility/clean.rb +312 -1
  334. package/project/.sdk/tm/rb/utility/done.rb +15 -5
  335. package/project/.sdk/tm/rb/utility/make_error.rb +13 -4
  336. package/project/.sdk/tm/rb/utility/make_options.rb +31 -12
  337. package/project/.sdk/tm/rb/utility/register.rb +2 -0
  338. package/project/.sdk/tm/rust/core/context.rs +55 -0
  339. package/project/.sdk/tm/rust/core/utility_type.rs +17 -0
  340. package/project/.sdk/tm/rust/feature/audit.rs +2 -0
  341. package/project/.sdk/tm/rust/feature/cost.rs +3 -2
  342. package/project/.sdk/tm/rust/feature/debug.rs +16 -16
  343. package/project/.sdk/tm/rust/feature/log.rs +42 -7
  344. package/project/.sdk/tm/rust/feature/proxy.rs +48 -2
  345. package/project/.sdk/tm/rust/feature/secrets.rs +12 -0
  346. package/project/.sdk/tm/rust/feature/telemetry.rs +2 -0
  347. package/project/.sdk/tm/rust/tests/feature_test.rs +2 -2
  348. package/project/.sdk/tm/rust/utility/clean.rs +446 -5
  349. package/project/.sdk/tm/rust/utility/done.rs +22 -12
  350. package/project/.sdk/tm/rust/utility/make_error.rs +4 -1
  351. package/project/.sdk/tm/rust/utility/make_options.rs +73 -19
  352. package/project/.sdk/tm/scala/Makefile +3 -1
  353. package/project/.sdk/tm/scala/core/Context.scala +16 -0
  354. package/project/.sdk/tm/scala/core/SdkClient.scala +14 -4
  355. package/project/.sdk/tm/scala/core/SdkError.scala +28 -0
  356. package/project/.sdk/tm/scala/core/Types.scala +3 -0
  357. package/project/.sdk/tm/scala/core/Utility.scala +2 -0
  358. package/project/.sdk/tm/scala/feature/AuditFeature.scala +16 -10
  359. package/project/.sdk/tm/scala/feature/CostFeature.scala +10 -5
  360. package/project/.sdk/tm/scala/feature/DebugFeature.scala +24 -21
  361. package/project/.sdk/tm/scala/feature/LogFeature.scala +9 -4
  362. package/project/.sdk/tm/scala/feature/ProxyFeature.scala +23 -2
  363. package/project/.sdk/tm/scala/feature/SecretsFeature.scala +14 -0
  364. package/project/.sdk/tm/scala/feature/TelemetryFeature.scala +9 -2
  365. package/project/.sdk/tm/scala/sdktest/SdkTestMain.scala +2 -2
  366. package/project/.sdk/tm/scala/utility/Make.scala +63 -20
  367. package/project/.sdk/tm/scala/utility/Misc.scala +358 -5
  368. package/project/.sdk/tm/scala/utility/Register.scala +1 -0
  369. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +29 -0
  370. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +2 -0
  371. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/AuditFeature.swift +10 -9
  372. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/CostFeature.swift +7 -5
  373. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/DebugFeature.swift +19 -15
  374. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/FeatureOptions.swift +16 -0
  375. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/LogFeature.swift +4 -1
  376. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/ProxyFeature.swift +20 -5
  377. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/SecretsFeature.swift +13 -0
  378. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TelemetryFeature.swift +4 -2
  379. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeError.swift +15 -5
  380. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +58 -19
  381. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +1 -0
  382. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +391 -4
  383. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/FeatureTest.swift +2 -2
  384. package/project/.sdk/tm/ts/src/Context.ts +5 -1
  385. package/project/.sdk/tm/ts/src/feature/audit/AuditFeature.ts +2 -2
  386. package/project/.sdk/tm/ts/src/feature/cost/CostFeature.ts +2 -2
  387. package/project/.sdk/tm/ts/src/feature/debug/DebugFeature.ts +13 -7
  388. package/project/.sdk/tm/ts/src/feature/log/LogFeature.ts +9 -5
  389. package/project/.sdk/tm/ts/src/feature/proxy/ProxyFeature.ts +19 -1
  390. package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +12 -0
  391. package/project/.sdk/tm/ts/src/feature/telemetry/TelemetryFeature.ts +4 -2
  392. package/project/.sdk/tm/ts/src/utility/CleanUtility.ts +287 -9
  393. package/project/.sdk/tm/ts/src/utility/DoneUtility.ts +18 -5
  394. package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +18 -8
  395. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +38 -16
  396. package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -2
  397. package/project/.sdk/tm/ts/test/feature/harness.ts +11 -1
  398. package/project/.sdk/tm/ts/test/feature.test.ts +9 -2
  399. package/project/.sdk/tm/zig/core/context.zig +34 -0
  400. package/project/.sdk/tm/zig/core/error.zig +22 -1
  401. package/project/.sdk/tm/zig/core/utility.zig +403 -39
  402. package/project/.sdk/tm/zig/feature/audit.zig +4 -2
  403. package/project/.sdk/tm/zig/feature/cost.zig +3 -2
  404. package/project/.sdk/tm/zig/feature/debug.zig +20 -25
  405. package/project/.sdk/tm/zig/feature/log.zig +3 -1
  406. package/project/.sdk/tm/zig/feature/proxy.zig +47 -6
  407. package/project/.sdk/tm/zig/feature/secrets.zig +7 -0
  408. package/project/.sdk/tm/zig/feature/telemetry.zig +4 -2
  409. package/project/.sdk/tm/zig/test/feature_test.zig +2 -2
  410. package/project/sdkgen-package.json +1 -1
  411. package/src/helpers/naming.ts +1 -1
@@ -9,6 +9,7 @@ import { cmp, each, Folder, entityCollection,
9
9
 
10
10
  import { TestEntity } from './TestEntity_java'
11
11
  import { TestDirect } from './TestDirect_java'
12
+ import { TestClean } from './TestClean_java'
12
13
  import { ReadmeExamplesTest } from './ReadmeExamplesTest_java'
13
14
  import { javaPackage } from './utility_java'
14
15
 
@@ -23,6 +24,7 @@ const Test = cmp(function Test(props: any) {
23
24
 
24
25
  // Write-once: a project's edited control file survives regeneration.
25
26
  TestControl({ target, dir: 'test' })
27
+ TestClean({ target, javapackage })
26
28
 
27
29
  const entity = each(entityCollection(model))
28
30
  .filter((e: any) => false !== e.active)
@@ -5,6 +5,7 @@ import java.util.Iterator;
5
5
  import java.util.LinkedHashMap;
6
6
  import java.util.List;
7
7
  import java.util.Map;
8
+ import java.util.NoSuchElementException;
8
9
  import java.util.Spliterator;
9
10
  import java.util.Spliterators;
10
11
  import java.util.function.BooleanSupplier;
@@ -163,15 +164,31 @@ public abstract class EntityBase implements SdkEntity {
163
164
  return out;
164
165
  }
165
166
  catch (RuntimeException err) {
166
- // An error already finalised by makeError (e.g. via done) must not
167
- // be wrapped a second time.
168
- if (err == ctx.ctrl.err) {
169
- throw err;
170
- }
171
- return utility.makeError.apply(ctx, err);
167
+ return unexpected(ctx, err);
168
+ }
169
+ }
170
+
171
+ // The catch path. An error already finalised by makeError (e.g. via done)
172
+ // must not be wrapped a second time.
173
+ private Object unexpected(Context ctx, RuntimeException err) {
174
+ if (err == ctx.ctrl.err) {
175
+ throw err;
176
+ }
177
+ try {
178
+ return this.utility.makeError.apply(ctx, err);
179
+ }
180
+ catch (RuntimeException thrown) {
181
+ throw thrown == ctx.ctrl.err ? thrown : cleanError(ctx, thrown);
172
182
  }
173
183
  }
174
184
 
185
+ // makeError fires PreUnexpected; an error a hook throws there escapes it,
186
+ // even under throw false, so it is cleaned here.
187
+ private RuntimeException cleanError(Context ctx, RuntimeException err) {
188
+ Object cleaned = this.utility.clean.apply(ctx, err);
189
+ return cleaned instanceof RuntimeException ? (RuntimeException) cleaned : err;
190
+ }
191
+
175
192
  /**
176
193
  * Streaming operations. Runs `action` through the full pipeline and
177
194
  * returns a Stream over result items, so the streaming feature's
@@ -227,9 +244,14 @@ public abstract class EntityBase implements SdkEntity {
227
244
 
228
245
  // Inbound: prefer the streaming feature's incremental iterator; else fall
229
246
  // back to the materialised items so `stream` always yields.
230
- Iterator<Object> source;
247
+ Iterator<Object> source = null;
231
248
  if (ctx.result != null && ctx.result.stream != null) {
232
- source = ctx.result.stream.get();
249
+ try {
250
+ source = ctx.result.stream.get();
251
+ }
252
+ catch (RuntimeException err) {
253
+ unexpected(ctx, err);
254
+ }
233
255
  }
234
256
  else {
235
257
  List<Object> items;
@@ -246,19 +268,42 @@ public abstract class EntityBase implements SdkEntity {
246
268
  source = items.iterator();
247
269
  }
248
270
 
271
+ // The caller iterates after runOp has returned, so a failing source takes
272
+ // the catch path here. Both source calls sit in hasNext: under throw
273
+ // false the stream then ends rather than failing in next.
249
274
  final Iterator<Object> src = source;
250
275
  Iterator<Object> guarded = new Iterator<Object>() {
276
+ private boolean ended = src == null;
277
+ private boolean ready = false;
278
+ private Object item;
279
+
251
280
  @Override
252
281
  public boolean hasNext() {
253
- if (signal != null && signal.getAsBoolean()) {
282
+ if (ended || (signal != null && signal.getAsBoolean())) {
254
283
  return false;
255
284
  }
256
- return src.hasNext();
285
+ if (!ready) {
286
+ try {
287
+ ready = src.hasNext();
288
+ ended = !ready;
289
+ item = ready ? src.next() : null;
290
+ }
291
+ catch (RuntimeException err) {
292
+ ended = true;
293
+ ready = false;
294
+ unexpected(ctx, err);
295
+ }
296
+ }
297
+ return ready;
257
298
  }
258
299
 
259
300
  @Override
260
301
  public Object next() {
261
- return src.next();
302
+ if (!hasNext()) {
303
+ throw new NoSuchElementException();
304
+ }
305
+ ready = false;
306
+ return item;
262
307
  }
263
308
  };
264
309
 
@@ -1,5 +1,10 @@
1
1
  package JAVAPACKAGE.core;
2
2
 
3
+ import java.util.LinkedHashMap;
4
+ import java.util.Map;
5
+
6
+ import JAVAPACKAGE.utility.struct.Struct;
7
+
3
8
  /**
4
9
  * ProjectName SDK error. Carries the SDK error code, the operation
5
10
  * context, and cleaned copies of the result and spec at failure time.
@@ -9,9 +14,13 @@ public class SdkError extends RuntimeException {
9
14
  public final String sdk = "ProjectName";
10
15
  public String code;
11
16
  public String msg;
12
- public transient Context ctx;
13
- public transient Object result;
14
- public transient Object spec;
17
+ public Object result;
18
+ public Object spec;
19
+
20
+ // Reachable for a debugger, invisible to a serialiser: the context holds
21
+ // the live spec and options, and an error is what gets logged. Private,
22
+ // so a reflective walk of the public fields never reaches it.
23
+ private transient Context ctx;
15
24
 
16
25
  /**
17
26
  * HTTP status of the response that caused this error, or -1 when the
@@ -32,8 +41,32 @@ public class SdkError extends RuntimeException {
32
41
  this.ctx = ctx;
33
42
  }
34
43
 
44
+ /** The operation context at failure time, for a debugger; never printed. */
45
+ public Context ctx() {
46
+ return this.ctx;
47
+ }
48
+
35
49
  @Override
36
50
  public String getMessage() {
37
51
  return this.msg;
38
52
  }
53
+
54
+ /** What makeError attached is already cleaned; the context is not part of the record. */
55
+ public Map<String, Object> toMap() {
56
+ Map<String, Object> out = new LinkedHashMap<>();
57
+ out.put("sdk", this.sdk);
58
+ out.put("code", this.code);
59
+ out.put("message", this.msg);
60
+ out.put("status", this.status);
61
+ out.put("result", this.result);
62
+ out.put("spec", this.spec);
63
+ return out;
64
+ }
65
+
66
+ @Override
67
+ public String toString() {
68
+ return "ProjectNameSDK error [" + this.code + "] " + this.msg
69
+ + " (status " + this.status + ")"
70
+ + (this.spec == null ? "" : " spec=" + Struct.jsonify(this.spec, Map.of("indent", 0)));
71
+ }
39
72
  }
@@ -119,6 +119,9 @@ ${cookieHelper(spec.where)}
119
119
  }
120
120
  else {
121
121
  const b64 = Buffer.from(apikey + ':' + pass).toString('base64')
122
+ // The joined, encoded pair is a wire form neither credential's own
123
+ // registration covers.
124
+ utility.cleanAdd(ctx, b64)
122
125
  setprop(headers, CRED_name,
123
126
  options.auth.prefix ? options.auth.prefix + ' ' + b64 : b64)
124
127
  }
@@ -0,0 +1,458 @@
1
+ import {
2
+ cmp,
3
+ File,
4
+ Content,
5
+ isAuthSuppressed,
6
+ isHttpBasicAuth,
7
+ resolveAuthIn,
8
+ resolveAuthName,
9
+ } from '@voxgig/sdkgen'
10
+
11
+
12
+ // The canary sweep: every credential slot holds a distinctive value, every
13
+ // diagnostic feature this SDK ships is switched on with a capturing sink, a
14
+ // real operation runs through every outcome, and every string that leaves
15
+ // the SDK is searched for the canaries and their encoded forms. It also
16
+ // proves its own sensitivity: with clean switched off the canary MUST show.
17
+ const TestClean = cmp(function TestClean(props: any) {
18
+ const { model } = props.ctx$
19
+
20
+ const auth = {
21
+ suppressed: isAuthSuppressed(model),
22
+ where: resolveAuthIn(model),
23
+ name: 'header' === resolveAuthIn(model)
24
+ ? resolveAuthName(model).toLowerCase() : resolveAuthName(model),
25
+ basic: isHttpBasicAuth(model),
26
+ }
27
+
28
+ File({ name: 'clean.test.js' }, () => Content(render(auth)))
29
+ })
30
+
31
+
32
+ function render(auth: {
33
+ suppressed: boolean, where: string, name: string, basic: boolean
34
+ }): string {
35
+ return `const { test, describe } = require('node:test')
36
+ const { ok, equal, deepStrictEqual } = require('node:assert')
37
+ const { inspect } = require('node:util')
38
+
39
+ const { SDK, BaseFeature } = require('..')
40
+ const { hasFeature } = require('./feature/harness')
41
+
42
+
43
+ // Generated: the credential's wire placement is fixed when the SDK is built.
44
+ const AUTH = ${JSON.stringify(auth)}
45
+
46
+ const CANARY = {
47
+ apikey: 'CANARY-APIKEY-k9x2m7q4p1',
48
+ secret: 'CANARY-SECRET-w3e8r5t2y6',
49
+ header: 'CANARY-HEADER-z1x4c7v0b3',
50
+ value: 'CANARY-VALUE-n5m8b2v9c4',
51
+ config: 'CANARY-CONFIG-h6j3k8l2m5',
52
+ }
53
+
54
+ const MASK = '[redacted]'
55
+
56
+ // Every form a canary can travel in.
57
+ const FORMS = []
58
+ for (const v of Object.values(CANARY)) {
59
+ FORMS.push(v, Buffer.from(v).toString('base64'), encodeURIComponent(v))
60
+ }
61
+ FORMS.push(Buffer.from(CANARY.apikey + ':' + CANARY.secret).toString('base64'))
62
+
63
+
64
+ // Header maps keep the caller's spelling; the assertion should not care.
65
+ function header(map, name) {
66
+ for (const k of Object.keys(map || {})) {
67
+ if (k.toLowerCase() === name.toLowerCase()) return map[k]
68
+ }
69
+ return undefined
70
+ }
71
+
72
+
73
+ function leaks(text) {
74
+ return FORMS.filter((f) => text.includes(f))
75
+ }
76
+
77
+
78
+ function forms(name, val) {
79
+ const out = []
80
+ const push = (kind, fn) => {
81
+ try { out.push({ name: name + ':' + kind, text: fn() }) } catch (_e) { }
82
+ }
83
+ push('json', () => JSON.stringify(val))
84
+ push('string', () => String(val))
85
+ push('inspect', () => inspect(val, { depth: 8 }))
86
+ if (val instanceof Error) {
87
+ push('message', () => String(val.message))
88
+ push('stack', () => String(val.stack))
89
+ push('props', () => inspect({ ...val }, { depth: 8 }))
90
+ }
91
+ return out
92
+ }
93
+
94
+
95
+ // Captures the serialised context from inside the pipeline: what a hook
96
+ // author would hand to a logger.
97
+ class CaptureFeature extends BaseFeature {
98
+ name = 'capture'
99
+ version = '0.0.1'
100
+ active = true
101
+ _sinks
102
+ constructor(sinks) { super(); this._sinks = sinks }
103
+ init() { }
104
+ PreRequest(ctx) { this._sinks.push(...forms('ctx@PreRequest', ctx)) }
105
+ PreResponse(ctx) { this._sinks.push(...forms('ctx@PreResponse', ctx)) }
106
+ // The SDK's own error as a hook reads it, which an observability feature logs.
107
+ PreUnexpected(ctx) {
108
+ this._sinks.push(...forms('ctx@PreUnexpected', ctx))
109
+ if (ctx.ctrl?.err instanceof Error) this._sinks.push(...forms('ctrl.err@PreUnexpected', ctx.ctrl.err))
110
+ }
111
+ }
112
+
113
+
114
+ function response(status, data, headers) {
115
+ const h = { 'content-type': 'application/json', ...(headers || {}) }
116
+ return {
117
+ status,
118
+ statusText: status < 400 ? 'OK' : 'ERR',
119
+ json: async () => data,
120
+ text: async () => JSON.stringify(data),
121
+ headers: {
122
+ get(key) { return h[String(key).toLowerCase()] },
123
+ forEach(cb) { Object.keys(h).forEach((k) => cb(h[k], k, this)) },
124
+ },
125
+ }
126
+ }
127
+
128
+ const SCENARIOS = [
129
+ { name: 'ok', respond: () => response(200, { id: 'i1', name: 'n1' },
130
+ { 'x-session-token': 'RESP-TOKEN-a1b2c3d4e5' }) },
131
+ { name: 'notfound', respond: () => response(404, { error: 'no such record' }) },
132
+ { name: 'server', respond: () => response(500, { error: 'boom' }) },
133
+ { name: 'transport', respond: (url) => {
134
+ throw new Error('socket hang up (URL was: "' + url + '")')
135
+ } },
136
+ { name: 'notjson', respond: () => ({
137
+ status: 200, statusText: 'OK',
138
+ json: async () => { throw new Error('Unexpected token < in JSON') },
139
+ text: async () => '<html>',
140
+ headers: { get() { return undefined }, forEach() { } },
141
+ }) },
142
+ // The SDK's own error, its code quoting a registered value.
143
+ { name: 'coded', respond: (_url, _fetchdef, ctx) => {
144
+ throw ctx.error('denied_' + CANARY.apikey, 'coded failure')
145
+ } },
146
+ ]
147
+
148
+
149
+ function makeSdk(scenario, sinks, cleanopts, extra) {
150
+ const capture = (name) => (rec) => { sinks.push(...forms(name, rec)) }
151
+ const feature = {}
152
+ if (hasFeature('log')) {
153
+ const logger = {}
154
+ for (const level of ['trace', 'debug', 'info', 'warn', 'error', 'fatal']) {
155
+ logger[level] = capture('log.' + level)
156
+ }
157
+ feature.log = { active: true, logger }
158
+ }
159
+ if (hasFeature('debug')) feature.debug = { active: true, onEntry: capture('debug') }
160
+ if (hasFeature('audit')) feature.audit = { active: true, sink: capture('audit') }
161
+ if (hasFeature('telemetry')) feature.telemetry = { active: true, exporter: capture('telemetry') }
162
+ if (hasFeature('cost')) feature.cost = { active: true, sink: capture('cost') }
163
+ if (hasFeature('metrics')) feature.metrics = { active: true }
164
+ if (hasFeature('clienttrack')) feature.clienttrack = { active: true }
165
+
166
+ const opts = {
167
+ apikey: CANARY.apikey,
168
+ secret: CANARY.secret,
169
+ headers: { 'X-Custom-Token': CANARY.header },
170
+ feature,
171
+ extend: [new CaptureFeature(sinks), ...(extra || [])],
172
+ utility: {
173
+ fetcher: async (ctx, url, fetchdef) => scenario.respond(url, fetchdef, ctx),
174
+ },
175
+ }
176
+ // null builds the client with no clean block at all, as most callers do.
177
+ if (null !== cleanopts) opts.clean = { values: CANARY.value, ...(cleanopts || {}) }
178
+ return new SDK(opts)
179
+ }
180
+
181
+
182
+ // The first operation that completes against a plain 200: with no
183
+ // arguments, else with every path parameter its points declare filled in.
184
+ // Resolves to { accessor, op, match }.
185
+ async function usableOp() {
186
+ const plain = new SDK({
187
+ apikey: CANARY.apikey,
188
+ utility: { fetcher: async () => response(200, { id: 'i1' }) },
189
+ })
190
+ const entities = plain._rootctx.config.entity || {}
191
+ const rank = (op) => (({ list: 0, load: 1 })[op] ?? 2)
192
+ for (const m of Object.getOwnPropertyNames(Object.getPrototypeOf(plain)).sort()) {
193
+ if (!/^[A-Z]/.test(m) || 'function' !== typeof plain[m]) { continue }
194
+ let inst
195
+ try { inst = plain[m]() } catch (_e) { continue }
196
+ if (null == inst || 'string' !== typeof inst.name || null == entities[inst.name]) { continue }
197
+ const opdefs = entities[inst.name].op || {}
198
+ for (const op of Object.keys(opdefs).sort((a, b) => rank(a) - rank(b))) {
199
+ const filled = {}
200
+ for (const point of opdefs[op].points || []) {
201
+ for (const p of point?.args?.params || []) {
202
+ if ('string' === typeof p?.name) filled[p.name] = 'p1'
203
+ }
204
+ }
205
+ for (const match of [{}, filled]) {
206
+ try {
207
+ await plain[m]()[op]({ ...match }, {})
208
+ return { accessor: m, op, match }
209
+ }
210
+ catch (_e) { continue }
211
+ }
212
+ }
213
+ }
214
+ return null
215
+ }
216
+
217
+
218
+ // A feature that throws from inside the pipeline, quoting the request it
219
+ // saw: an error makeError never handled.
220
+ class ThrowFeature extends BaseFeature {
221
+ name = 'throwhook'
222
+ version = '0.0.1'
223
+ active = true
224
+ constructor(unexpected = false) { super(); this._unexpected = unexpected }
225
+ init() { }
226
+ PreResponse(ctx) {
227
+ throw new Error('hook saw ' + JSON.stringify(ctx.spec))
228
+ }
229
+ // Fired from the operation's catch block, before its cleaning.
230
+ PreUnexpected(ctx) {
231
+ if (this._unexpected) throw new Error('hook saw ' + JSON.stringify(ctx.spec))
232
+ }
233
+ }
234
+
235
+
236
+ // A stream that fails while the caller iterates it, quoting a credential.
237
+ class StreamThrowFeature extends BaseFeature {
238
+ name = 'streamthrow'
239
+ version = '0.0.1'
240
+ active = true
241
+ init() { }
242
+ PreDone(ctx) {
243
+ ctx.result.stream = async function* () { throw new Error('stream saw ' + CANARY.apikey) }
244
+ }
245
+ }
246
+
247
+
248
+ // A stream that succeeds, so the pipeline's terminal step never runs.
249
+ class StreamOkFeature extends BaseFeature {
250
+ name = 'streamok'
251
+ version = '0.0.1'
252
+ active = true
253
+ init() { }
254
+ PreDone(ctx) {
255
+ const items = [].concat(ctx.result.resdata ?? [])
256
+ ctx.result.stream = async function* () { yield* items }
257
+ }
258
+ }
259
+
260
+
261
+ async function drive(sdk, target, ctrl, sinks) {
262
+ // A caller may keep the record it passed rather than read ctrl.explain.
263
+ const held = ctrl.explain
264
+ let out = undefined
265
+ let err = undefined
266
+ try {
267
+ out = await sdk[target.accessor]()[target.op]({ ...target.match }, ctrl)
268
+ }
269
+ catch (e) {
270
+ err = e
271
+ }
272
+ if (undefined !== err) sinks.push(...forms('error', err))
273
+ if (undefined !== out) sinks.push(...forms('result', out))
274
+ if (null != ctrl.explain) sinks.push(...forms('explain', ctrl.explain))
275
+ if (null != held && held !== ctrl.explain) sinks.push(...forms('explain:held', held))
276
+ return err
277
+ }
278
+
279
+
280
+ describe('clean', () => {
281
+ test('no credential leaves the SDK in any form', async (t) => {
282
+ const target = await usableOp()
283
+ if (null == target) {
284
+ return t.skip('no operation of this SDK completes against a plain 200; nothing to sweep')
285
+ }
286
+
287
+ const sinks = []
288
+ const errors = {}
289
+ const explains = {}
290
+
291
+ for (const scenario of SCENARIOS) {
292
+ for (const variant of [
293
+ { name: 'throw', ctrl: () => ({}) },
294
+ { name: 'explain', ctrl: () => ({ explain: {} }) },
295
+ { name: 'nothrow', ctrl: () => ({ throw: false, explain: {} }) },
296
+ ]) {
297
+ const sdk = makeSdk(scenario, sinks)
298
+ const ctrl = variant.ctrl()
299
+ const err = await drive(sdk, target, ctrl, sinks)
300
+ const key = scenario.name + '/' + variant.name
301
+ if (null != err) errors[key] = err
302
+ if (null != ctrl.explain) explains[key] = ctrl.explain
303
+ sinks.push(...forms('sdk', sdk))
304
+ sinks.push({ name: 'sdk:spread', text: inspect({ ...sdk }, { depth: 6 }) })
305
+ }
306
+ }
307
+
308
+ // A credential mistyped as an object is rejected by validation, whose
309
+ // message quotes the value it rejected; with and without a clean block.
310
+ for (const cleanblock of [{ clean: { values: CANARY.value } }, {}]) {
311
+ let rejected = undefined
312
+ try {
313
+ new SDK({ apikey: { value: CANARY.apikey }, ...cleanblock })
314
+ }
315
+ catch (e) {
316
+ rejected = e
317
+ }
318
+ ok(null != rejected, 'a credential mistyped as an object should be rejected')
319
+ sinks.push(...forms('rejected', rejected))
320
+ }
321
+
322
+ // An error a feature hook throws, quoting the request, skips makeError.
323
+ for (const unexpected of [false, true]) {
324
+ const hooked = makeSdk(SCENARIOS[0], sinks, undefined, [new ThrowFeature(unexpected)])
325
+ const hookerr = await drive(hooked, target, { explain: {} }, sinks)
326
+ ok(null != hookerr, 'the throwing hook should fail the operation')
327
+ }
328
+
329
+ // Iterating a stream runs inside the same catch path as the operation,
330
+ // and the explain record the caller passed is cleaned however it ends.
331
+ for (const [name, extra] of [['stream', [new StreamThrowFeature()]],
332
+ ['stream-ok', [new StreamOkFeature()]], ['stream-plain', []]]) {
333
+ const streamed = makeSdk(SCENARIOS[0], sinks, undefined, extra)
334
+ const explain = {}
335
+ let streamerr = undefined
336
+ try {
337
+ for await (const _item of streamed[target.accessor]().stream(
338
+ target.op, { reqmatch: { ...target.match } }, { ctrl: { explain } })) { }
339
+ }
340
+ catch (e) { streamerr = e }
341
+ ok(('stream' === name) === (null != streamerr), name + ': only the failing stream throws')
342
+ if (null != streamerr) sinks.push(...forms(name, streamerr))
343
+ ok(0 < Object.keys(explain).length, name + ': the explain record was not filled')
344
+ sinks.push(...forms(name + ':explain', explain))
345
+ }
346
+
347
+ // Most callers pass no clean block; the defaults alone must mask.
348
+ for (const scenario of [SCENARIOS[1], SCENARIOS[3]]) {
349
+ const bare = makeSdk(scenario, sinks, null)
350
+ await drive(bare, target, { explain: {} }, sinks)
351
+ sinks.push(...forms('bare', bare))
352
+ }
353
+
354
+ // The generated config's own clean block is read beside the caller's,
355
+ // and is not changed by it.
356
+ const util = makeSdk(SCENARIOS[0], sinks).utility()
357
+ const cfgclean = { keys: 'zzsens', values: CANARY.config }
358
+ const built = util.makeOptions({ utility: util, config: { options: { clean: cfgclean } },
359
+ options: { clean: { values: CANARY.value } } })
360
+ const seeded = util.clean({ options: built }, 'config ' + CANARY.config + ' caller ' + CANARY.value)
361
+ sinks.push({ name: 'config-clean', text: seeded })
362
+
363
+ // A feature's name is not a field name: only the sensitive names inside
364
+ // its settings register. An entity block, of per-entity settings or seeded
365
+ // records keyed by entity name and id, is not read at all.
366
+ const featured = new SDK({ apikey: CANARY.apikey, feature: {
367
+ zzsecrets: { active: false, kind: 'PLAINSETTING-q8w2e4r6' },
368
+ zzfeat: { active: false, apitoken: 'FEATTOKEN-z9y8x7w6' },
369
+ test: { active: false, entity: { zztoken: { ZZTOKEN01: { note: 'PLAINRECORD-t5r3e1w9' } } } },
370
+ }, entity: { zztoken: { alias: { zzkey: 'PLAINALIAS-m2n4b6v8' } } } })
371
+ const fctx = { options: featured._options }
372
+
373
+ // The raw path returns its failure rather than throwing it.
374
+ const raw = await makeSdk(SCENARIOS[3], sinks).direct({ path: 'raw' })
375
+ ok(false === raw.ok && null != raw.err, 'a transport failure should fail direct()')
376
+ sinks.push(...forms('direct', raw.err))
377
+
378
+ const leaked = sinks
379
+ .map((s) => ({ name: s.name, found: leaks(s.text) }))
380
+ .filter((s) => 0 < s.found.length)
381
+
382
+ console.log('clean: swept ' + sinks.length + ' surface(s), ' + leaked.length + ' leak(s)')
383
+
384
+ equal(leaked.length, 0, 'credential leaked through: ' +
385
+ leaked.map((l) => l.name + ' [' + l.found.join(', ') + ']').join('; '))
386
+
387
+ // The positive half: the slot the credential travelled in is masked,
388
+ // and an unregistered token in a response header is masked by name.
389
+ const notfound = errors['notfound/throw']
390
+ ok(null != notfound, 'the 404 scenario must throw')
391
+ equal(notfound.status, 404)
392
+ if (!AUTH.suppressed) {
393
+ const spec = notfound.spec || {}
394
+ if ('query' === AUTH.where) {
395
+ equal(header(spec.query, AUTH.name), MASK)
396
+ }
397
+ else if ('cookie' === AUTH.where) {
398
+ ok(String(header(spec.headers, 'cookie')).includes(MASK), 'cookie: ' + header(spec.headers, 'cookie'))
399
+ }
400
+ else {
401
+ ok(String(header(spec.headers, AUTH.name)).endsWith(MASK),
402
+ AUTH.name + ': ' + header(spec.headers, AUTH.name))
403
+ }
404
+ }
405
+ equal(header(notfound.spec.headers, 'x-custom-token'), MASK)
406
+
407
+ equal(seeded, 'config ' + MASK + ' caller ' + MASK)
408
+ deepStrictEqual(util.clean({ options: built }, { my_zzsens: 'x', other: 'y' }), { my_zzsens: MASK, other: 'y' })
409
+ deepStrictEqual(cfgclean, { keys: 'zzsens', values: CANARY.config })
410
+
411
+ equal(featured.utility().clean(fctx, 'kind PLAINSETTING-q8w2e4r6'), 'kind PLAINSETTING-q8w2e4r6')
412
+ equal(featured.utility().clean(fctx, 'token FEATTOKEN-z9y8x7w6'), 'token ' + MASK)
413
+ equal(featured.utility().clean(fctx, 'record PLAINRECORD-t5r3e1w9'), 'record PLAINRECORD-t5r3e1w9')
414
+ equal(featured.utility().clean(fctx, 'alias PLAINALIAS-m2n4b6v8'), 'alias PLAINALIAS-m2n4b6v8')
415
+
416
+ const coded = errors['coded/throw']
417
+ ok(null != coded, 'the coded scenario must throw')
418
+ equal(coded.code, 'denied_' + MASK)
419
+
420
+ const explained = explains['ok/explain'] || {}
421
+ ok(null != explained.result, 'the explain record should carry the result')
422
+ equal(header(explained.result.headers, 'x-session-token'), MASK)
423
+ })
424
+
425
+
426
+ test('the sweep can see a leak: clean switched off shows the credential', async (t) => {
427
+ const target = await usableOp()
428
+ if (null == target) {
429
+ return t.skip('no operation of this SDK completes against a plain 200; nothing to sweep')
430
+ }
431
+
432
+ const sinks = []
433
+ const sdk = makeSdk(SCENARIOS[1], sinks, { active: false })
434
+ const err = await drive(sdk, target, {}, sinks)
435
+ ok(null != err)
436
+
437
+ // Explaining a failure must not cost it its error.
438
+ const explained = await drive(makeSdk(SCENARIOS[1], [], { active: false }), target, { explain: {} }, [])
439
+ equal(explained?.message, err.message, 'with clean off, explain lost the error')
440
+
441
+ const leaked = sinks.filter((s) => 0 < leaks(s.text).length)
442
+ ok(0 < leaked.length, 'with clean off, nothing showed the canary: the sweep is blind')
443
+
444
+ if (!AUTH.suppressed) {
445
+ const text = JSON.stringify(err.spec)
446
+ ok(text.includes(CANARY.apikey) ||
447
+ text.includes(Buffer.from(CANARY.apikey + ':' + CANARY.secret).toString('base64')),
448
+ 'the raw spec should carry the credential when clean is off')
449
+ }
450
+ })
451
+ })
452
+ `
453
+ }
454
+
455
+
456
+ export {
457
+ TestClean
458
+ }
@@ -9,6 +9,7 @@ import { cmp, each, Folder, entityCollection,
9
9
 
10
10
  import { TestLive } from './TestLive_js'
11
11
  import { TestDefinition } from './TestDefinition_js'
12
+ import { TestClean } from './TestClean_js'
12
13
  import { TestDirect } from './TestDirect_js'
13
14
  import { TestEntity } from './TestEntity_js'
14
15
 
@@ -23,6 +24,7 @@ const Test = cmp(function Test(props: any) {
23
24
  TestControl({ target, dir: 'test' })
24
25
  TestLive({ target })
25
26
  TestDefinition({ target })
27
+ TestClean({ target })
26
28
 
27
29
  Folder({ name: 'entity' }, () => {
28
30
  const entity = each(entityCollection(model))