@voxgig/sdkgen 4.32.1 → 4.34.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 (442) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/action/copies.d.ts +21 -0
  3. package/dist/action/copies.js +146 -0
  4. package/dist/action/copies.js.map +1 -0
  5. package/dist/action/doctor.d.ts +15 -2
  6. package/dist/action/doctor.js +169 -23
  7. package/dist/action/doctor.js.map +1 -1
  8. package/dist/action/edition.js +6 -2
  9. package/dist/action/edition.js.map +1 -1
  10. package/dist/action/feature.js +6 -2
  11. package/dist/action/feature.js.map +1 -1
  12. package/dist/action/package.js +28 -10
  13. package/dist/action/package.js.map +1 -1
  14. package/dist/action/remove.js +2 -0
  15. package/dist/action/remove.js.map +1 -1
  16. package/dist/action/resolve.d.ts +1 -0
  17. package/dist/action/resolve.js +10 -2
  18. package/dist/action/resolve.js.map +1 -1
  19. package/dist/action/target.js +6 -2
  20. package/dist/action/target.js.map +1 -1
  21. package/dist/helpers/naming.js +1 -1
  22. package/dist/helpers/naming.js.map +1 -1
  23. package/dist/sdkgen.d.ts +2 -1
  24. package/dist/sdkgen.js +36 -3
  25. package/dist/sdkgen.js.map +1 -1
  26. package/dist/tsconfig.tsbuildinfo +1 -1
  27. package/model/sdkgen.aontu +7 -1
  28. package/package.json +1 -1
  29. package/project/.sdk/model/feature/debug.aontu +3 -1
  30. package/project/.sdk/src/cmp/c/PrepareAuth_c.ts +8 -28
  31. package/project/.sdk/src/cmp/c/TestClean_c.ts +774 -0
  32. package/project/.sdk/src/cmp/c/Test_c.ts +3 -0
  33. package/project/.sdk/src/cmp/c/fragment/Entity.fragment.c +16 -5
  34. package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +1 -1
  35. package/project/.sdk/src/cmp/clojure/PrepareAuth_clojure.ts +3 -0
  36. package/project/.sdk/src/cmp/clojure/TestClean_clojure.ts +473 -0
  37. package/project/.sdk/src/cmp/clojure/Test_clojure.ts +6 -0
  38. package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +18 -8
  39. package/project/.sdk/src/cmp/cpp/PrepareAuth_cpp.ts +3 -0
  40. package/project/.sdk/src/cmp/cpp/TestClean_cpp.ts +782 -0
  41. package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +1 -1
  42. package/project/.sdk/src/cmp/cpp/Test_cpp.ts +2 -0
  43. package/project/.sdk/src/cmp/csharp/PrepareAuth_csharp.ts +3 -0
  44. package/project/.sdk/src/cmp/csharp/TestClean_csharp.ts +887 -0
  45. package/project/.sdk/src/cmp/csharp/Test_csharp.ts +2 -0
  46. package/project/.sdk/src/cmp/csharp/fragment/EntityBase.fragment.cs +68 -4
  47. package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +8 -2
  48. package/project/.sdk/src/cmp/csharp/fragment/SdkError.fragment.cs +49 -0
  49. package/project/.sdk/src/cmp/elixir/PrepareAuth_elixir.ts +3 -0
  50. package/project/.sdk/src/cmp/elixir/Schema_elixir.ts +20 -10
  51. package/project/.sdk/src/cmp/elixir/TestClean_elixir.ts +666 -0
  52. package/project/.sdk/src/cmp/elixir/Test_elixir.ts +4 -0
  53. package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +1 -1
  54. package/project/.sdk/src/cmp/elixir/fragment/Pipeline.fragment.ex +14 -2
  55. package/project/.sdk/src/cmp/go/PrepareAuth_go.ts +3 -0
  56. package/project/.sdk/src/cmp/go/TestClean_go.ts +804 -0
  57. package/project/.sdk/src/cmp/go/Test_go.ts +3 -0
  58. package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +54 -4
  59. package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +27 -2
  60. package/project/.sdk/src/cmp/java/PrepareAuth_java.ts +3 -0
  61. package/project/.sdk/src/cmp/java/TestClean_java.ts +884 -0
  62. package/project/.sdk/src/cmp/java/Test_java.ts +2 -0
  63. package/project/.sdk/src/cmp/java/fragment/EntityBase.fragment.java +56 -11
  64. package/project/.sdk/src/cmp/java/fragment/SdkError.fragment.java +36 -3
  65. package/project/.sdk/src/cmp/js/PrepareAuth_js.ts +3 -0
  66. package/project/.sdk/src/cmp/js/TestClean_js.ts +458 -0
  67. package/project/.sdk/src/cmp/js/Test_js.ts +2 -0
  68. package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +5 -4
  69. package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +7 -1
  70. package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +7 -1
  71. package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +7 -1
  72. package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +7 -1
  73. package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +7 -1
  74. package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +11 -2
  75. package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +17 -1
  76. package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +5 -0
  77. package/project/.sdk/src/cmp/kotlin/PrepareAuth_kotlin.ts +3 -0
  78. package/project/.sdk/src/cmp/kotlin/TestClean_kotlin.ts +654 -0
  79. package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +3 -0
  80. package/project/.sdk/src/cmp/kotlin/fragment/EntityBase.fragment.kt +44 -11
  81. package/project/.sdk/src/cmp/kotlin/fragment/SdkError.fragment.kt +31 -0
  82. package/project/.sdk/src/cmp/lua/PrepareAuth_lua.ts +3 -0
  83. package/project/.sdk/src/cmp/lua/TestClean_lua.ts +769 -0
  84. package/project/.sdk/src/cmp/lua/Test_lua.ts +3 -0
  85. package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +77 -1
  86. package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +49 -2
  87. package/project/.sdk/src/cmp/ocaml/Entity_ocaml.ts +3 -2
  88. package/project/.sdk/src/cmp/ocaml/PrepareAuth_ocaml.ts +4 -25
  89. package/project/.sdk/src/cmp/ocaml/TestClean_ocaml.ts +538 -0
  90. package/project/.sdk/src/cmp/ocaml/Test_ocaml.ts +5 -0
  91. package/project/.sdk/src/cmp/ocaml/fragment/RunOp.fragment.ml +16 -4
  92. package/project/.sdk/src/cmp/perl/PrepareAuth_perl.ts +3 -0
  93. package/project/.sdk/src/cmp/perl/TestClean_perl.ts +619 -0
  94. package/project/.sdk/src/cmp/perl/Test_perl.ts +3 -0
  95. package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +67 -5
  96. package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +13 -1
  97. package/project/.sdk/src/cmp/php/PrepareAuth_php.ts +3 -0
  98. package/project/.sdk/src/cmp/php/TestClean_php.ts +809 -0
  99. package/project/.sdk/src/cmp/php/Test_php.ts +2 -0
  100. package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +96 -55
  101. package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +15 -2
  102. package/project/.sdk/src/cmp/py/PrepareAuth_py.ts +3 -0
  103. package/project/.sdk/src/cmp/py/TestClean_py.ts +549 -0
  104. package/project/.sdk/src/cmp/py/Test_py.ts +3 -0
  105. package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +83 -55
  106. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +19 -3
  107. package/project/.sdk/src/cmp/rb/PrepareAuth_rb.ts +3 -0
  108. package/project/.sdk/src/cmp/rb/TestClean_rb.ts +535 -0
  109. package/project/.sdk/src/cmp/rb/Test_rb.ts +3 -0
  110. package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +108 -46
  111. package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +12 -1
  112. package/project/.sdk/src/cmp/rust/PrepareAuth_rust.ts +9 -45
  113. package/project/.sdk/src/cmp/rust/TestClean_rust.ts +881 -0
  114. package/project/.sdk/src/cmp/rust/Test_rust.ts +3 -0
  115. package/project/.sdk/src/cmp/rust/fragment/Entity.fragment.rs +14 -6
  116. package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +17 -1
  117. package/project/.sdk/src/cmp/rust/fragment/SdkError.fragment.rs +34 -2
  118. package/project/.sdk/src/cmp/scala/PrepareAuth_scala.ts +3 -0
  119. package/project/.sdk/src/cmp/scala/TestClean_scala.ts +608 -0
  120. package/project/.sdk/src/cmp/scala/Test_scala.ts +3 -0
  121. package/project/.sdk/src/cmp/scala/fragment/EntityBase.fragment.scala +58 -6
  122. package/project/.sdk/src/cmp/swift/PrepareAuth_swift.ts +3 -0
  123. package/project/.sdk/src/cmp/swift/TestClean_swift.ts +671 -0
  124. package/project/.sdk/src/cmp/swift/Test_swift.ts +3 -0
  125. package/project/.sdk/src/cmp/swift/fragment/EntityBase.fragment.swift +10 -0
  126. package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +16 -2
  127. package/project/.sdk/src/cmp/swift/fragment/SdkError.fragment.swift +47 -3
  128. package/project/.sdk/src/cmp/ts/PrepareAuth_ts.ts +3 -0
  129. package/project/.sdk/src/cmp/ts/TestClean_ts.ts +465 -0
  130. package/project/.sdk/src/cmp/ts/Test_ts.ts +2 -0
  131. package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +5 -4
  132. package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +7 -1
  133. package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +7 -1
  134. package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +7 -1
  135. package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +7 -1
  136. package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +7 -1
  137. package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +8 -2
  138. package/project/.sdk/src/cmp/ts/fragment/SdkError.fragment.ts +20 -2
  139. package/project/.sdk/src/cmp/zig/PrepareAuth_zig.ts +3 -0
  140. package/project/.sdk/src/cmp/zig/TestClean_zig.ts +791 -0
  141. package/project/.sdk/src/cmp/zig/Test_zig.ts +5 -0
  142. package/project/.sdk/src/cmp/zig/fragment/Build.fragment.zig +19 -0
  143. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +14 -5
  144. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +1 -1
  145. package/project/.sdk/tm/c/core/context.c +25 -0
  146. package/project/.sdk/tm/c/core/error.c +16 -0
  147. package/project/.sdk/tm/c/core/sdk.h +22 -0
  148. package/project/.sdk/tm/c/feature/audit.c +2 -0
  149. package/project/.sdk/tm/c/feature/cost.c +1 -0
  150. package/project/.sdk/tm/c/feature/debug.c +19 -29
  151. package/project/.sdk/tm/c/feature/log.c +21 -2
  152. package/project/.sdk/tm/c/feature/proxy.c +55 -3
  153. package/project/.sdk/tm/c/feature/secrets.c +7 -0
  154. package/project/.sdk/tm/c/feature/telemetry.c +2 -0
  155. package/project/.sdk/tm/c/tests/feature_test.c +2 -2
  156. package/project/.sdk/tm/c/utility/clean.c +530 -8
  157. package/project/.sdk/tm/c/utility/done.c +28 -12
  158. package/project/.sdk/tm/c/utility/make_error.c +4 -3
  159. package/project/.sdk/tm/c/utility/make_options.c +71 -45
  160. package/project/.sdk/tm/clojure/feature/secrets/sdk/feature/secrets.clj +15 -0
  161. package/project/.sdk/tm/clojure/src/sdk/client.clj +20 -4
  162. package/project/.sdk/tm/clojure/src/sdk/core.clj +319 -35
  163. package/project/.sdk/tm/clojure/src/sdk/features.clj +68 -30
  164. package/project/.sdk/tm/clojure/test/sdk/test/feature.clj +4 -2
  165. package/project/.sdk/tm/clojure/test/sdk/test/pipeline.clj +47 -20
  166. package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +4 -0
  167. package/project/.sdk/tm/cpp/core/types.hpp +93 -3
  168. package/project/.sdk/tm/cpp/feature/audit.hpp +1 -0
  169. package/project/.sdk/tm/cpp/feature/cost.hpp +1 -0
  170. package/project/.sdk/tm/cpp/feature/debug.hpp +20 -12
  171. package/project/.sdk/tm/cpp/feature/log.hpp +31 -9
  172. package/project/.sdk/tm/cpp/feature/proxy.hpp +52 -6
  173. package/project/.sdk/tm/cpp/feature/secrets.hpp +13 -0
  174. package/project/.sdk/tm/cpp/feature/telemetry.hpp +4 -2
  175. package/project/.sdk/tm/cpp/test/feature_test.cpp +2 -2
  176. package/project/.sdk/tm/cpp/utility/pipeline.hpp +426 -51
  177. package/project/.sdk/tm/csharp/core/Context.cs +32 -0
  178. package/project/.sdk/tm/csharp/core/Utility.cs +2 -0
  179. package/project/.sdk/tm/csharp/feature/AuditFeature.cs +1 -0
  180. package/project/.sdk/tm/csharp/feature/CostFeature.cs +7 -5
  181. package/project/.sdk/tm/csharp/feature/DebugFeature.cs +19 -16
  182. package/project/.sdk/tm/csharp/feature/FeatureOptions.cs +16 -0
  183. package/project/.sdk/tm/csharp/feature/LogFeature.cs +4 -1
  184. package/project/.sdk/tm/csharp/feature/ProxyFeature.cs +26 -5
  185. package/project/.sdk/tm/csharp/feature/SecretsFeature.cs +16 -0
  186. package/project/.sdk/tm/csharp/feature/TelemetryFeature.cs +4 -2
  187. package/project/.sdk/tm/csharp/test/FeatureTest.cs +2 -2
  188. package/project/.sdk/tm/csharp/utility/Clean.cs +440 -2
  189. package/project/.sdk/tm/csharp/utility/Done.cs +27 -11
  190. package/project/.sdk/tm/csharp/utility/MakeError.cs +19 -8
  191. package/project/.sdk/tm/csharp/utility/MakeOptions.cs +119 -29
  192. package/project/.sdk/tm/csharp/utility/MakeResponse.cs +21 -11
  193. package/project/.sdk/tm/csharp/utility/Register.cs +1 -0
  194. package/project/.sdk/tm/elixir/lib/projectname/context.ex +19 -0
  195. package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +22 -1
  196. package/project/.sdk/tm/elixir/lib/projectname/error.ex +24 -0
  197. package/project/.sdk/tm/elixir/lib/projectname/feature/audit.ex +2 -2
  198. package/project/.sdk/tm/elixir/lib/projectname/feature/cost.ex +2 -2
  199. package/project/.sdk/tm/elixir/lib/projectname/feature/debug.ex +13 -13
  200. package/project/.sdk/tm/elixir/lib/projectname/feature/log.ex +18 -5
  201. package/project/.sdk/tm/elixir/lib/projectname/feature/proxy.ex +19 -1
  202. package/project/.sdk/tm/elixir/lib/projectname/feature/secrets.ex +15 -0
  203. package/project/.sdk/tm/elixir/lib/projectname/feature/telemetry.ex +4 -2
  204. package/project/.sdk/tm/elixir/lib/projectname/feature.ex +22 -0
  205. package/project/.sdk/tm/elixir/lib/projectname/utility.ex +464 -41
  206. package/project/.sdk/tm/elixir/test/feature_test.exs +3 -2
  207. package/project/.sdk/tm/go/core/context.go +42 -0
  208. package/project/.sdk/tm/go/core/error.go +30 -10
  209. package/project/.sdk/tm/go/core/utility_type.go +2 -0
  210. package/project/.sdk/tm/go/feature/audit_feature.go +1 -0
  211. package/project/.sdk/tm/go/feature/base_feature.go +12 -0
  212. package/project/.sdk/tm/go/feature/cost_feature.go +2 -2
  213. package/project/.sdk/tm/go/feature/debug_feature.go +14 -12
  214. package/project/.sdk/tm/go/feature/log_feature.go +13 -8
  215. package/project/.sdk/tm/go/feature/proxy_feature.go +26 -6
  216. package/project/.sdk/tm/go/feature/secrets_feature.go +19 -0
  217. package/project/.sdk/tm/go/feature/telemetry_feature.go +4 -2
  218. package/project/.sdk/tm/go/test/feature_test.go +2 -2
  219. package/project/.sdk/tm/go/utility/clean.go +585 -2
  220. package/project/.sdk/tm/go/utility/done.go +29 -9
  221. package/project/.sdk/tm/go/utility/make_error.go +51 -16
  222. package/project/.sdk/tm/go/utility/make_options.go +77 -36
  223. package/project/.sdk/tm/go/utility/register.go +12 -0
  224. package/project/.sdk/tm/java/core/Context.java +29 -0
  225. package/project/.sdk/tm/java/core/SdkClient.java +4 -2
  226. package/project/.sdk/tm/java/core/Utility.java +7 -0
  227. package/project/.sdk/tm/java/feature/AuditFeature.java +6 -0
  228. package/project/.sdk/tm/java/feature/CostFeature.java +5 -0
  229. package/project/.sdk/tm/java/feature/DebugFeature.java +25 -14
  230. package/project/.sdk/tm/java/feature/LogFeature.java +11 -4
  231. package/project/.sdk/tm/java/feature/ProxyFeature.java +41 -6
  232. package/project/.sdk/tm/java/feature/SecretsFeature.java +18 -0
  233. package/project/.sdk/tm/java/feature/TelemetryFeature.java +8 -2
  234. package/project/.sdk/tm/java/test/FeatureTest.java +2 -2
  235. package/project/.sdk/tm/java/utility/Clean.java +519 -1
  236. package/project/.sdk/tm/java/utility/Done.java +1 -1
  237. package/project/.sdk/tm/java/utility/MakeError.java +5 -1
  238. package/project/.sdk/tm/java/utility/MakeOptions.java +55 -31
  239. package/project/.sdk/tm/java/utility/Register.java +4 -0
  240. package/project/.sdk/tm/js/src/Context.js +5 -1
  241. package/project/.sdk/tm/js/src/feature/audit/AuditFeature.js +2 -2
  242. package/project/.sdk/tm/js/src/feature/cost/CostFeature.js +2 -2
  243. package/project/.sdk/tm/js/src/feature/debug/DebugFeature.js +13 -7
  244. package/project/.sdk/tm/js/src/feature/log/LogFeature.js +9 -5
  245. package/project/.sdk/tm/js/src/feature/proxy/ProxyFeature.js +19 -1
  246. package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +14 -0
  247. package/project/.sdk/tm/js/src/feature/telemetry/TelemetryFeature.js +4 -2
  248. package/project/.sdk/tm/js/src/utility/CleanUtility.js +294 -21
  249. package/project/.sdk/tm/js/src/utility/DoneUtility.js +17 -5
  250. package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +18 -2
  251. package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -15
  252. package/project/.sdk/tm/js/src/utility/Utility.js +4 -2
  253. package/project/.sdk/tm/js/test/feature/harness.js +11 -1
  254. package/project/.sdk/tm/js/test/feature.test.js +9 -2
  255. package/project/.sdk/tm/kotlin/core/Context.kt +19 -0
  256. package/project/.sdk/tm/kotlin/core/SdkClient.kt +9 -2
  257. package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
  258. package/project/.sdk/tm/kotlin/feature/AuditFeature.kt +11 -9
  259. package/project/.sdk/tm/kotlin/feature/CostFeature.kt +8 -5
  260. package/project/.sdk/tm/kotlin/feature/DebugFeature.kt +15 -22
  261. package/project/.sdk/tm/kotlin/feature/LogFeature.kt +8 -4
  262. package/project/.sdk/tm/kotlin/feature/ProxyFeature.kt +26 -2
  263. package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +11 -0
  264. package/project/.sdk/tm/kotlin/feature/TelemetryFeature.kt +4 -2
  265. package/project/.sdk/tm/kotlin/test/FeatureTest.kt +2 -2
  266. package/project/.sdk/tm/kotlin/utility/CoreUtil.kt +447 -11
  267. package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +38 -31
  268. package/project/.sdk/tm/kotlin/utility/Register.kt +1 -0
  269. package/project/.sdk/tm/lua/core/context.lua +43 -0
  270. package/project/.sdk/tm/lua/core/error.lua +36 -1
  271. package/project/.sdk/tm/lua/core/utility_type.lua +4 -0
  272. package/project/.sdk/tm/lua/feature/audit_feature.lua +2 -2
  273. package/project/.sdk/tm/lua/feature/cost_feature.lua +2 -2
  274. package/project/.sdk/tm/lua/feature/debug_feature.lua +21 -17
  275. package/project/.sdk/tm/lua/feature/log_feature.lua +2 -1
  276. package/project/.sdk/tm/lua/feature/proxy_feature.lua +23 -1
  277. package/project/.sdk/tm/lua/feature/secrets_feature.lua +18 -0
  278. package/project/.sdk/tm/lua/feature/telemetry_feature.lua +4 -2
  279. package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +3 -2
  280. package/project/.sdk/tm/lua/test/feature_test.lua +10 -3
  281. package/project/.sdk/tm/lua/utility/clean.lua +426 -2
  282. package/project/.sdk/tm/lua/utility/clean_explain.lua +34 -0
  283. package/project/.sdk/tm/lua/utility/done.lua +1 -7
  284. package/project/.sdk/tm/lua/utility/make_error.lua +3 -1
  285. package/project/.sdk/tm/lua/utility/make_options.lua +76 -30
  286. package/project/.sdk/tm/lua/utility/register.lua +4 -1
  287. package/project/.sdk/tm/ocaml/Makefile +5 -1
  288. package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +12 -1
  289. package/project/.sdk/tm/ocaml/sdk_features.ml +78 -18
  290. package/project/.sdk/tm/ocaml/sdk_helpers.ml +27 -0
  291. package/project/.sdk/tm/ocaml/sdk_runtime.ml +304 -26
  292. package/project/.sdk/tm/ocaml/sdk_types.ml +1 -0
  293. package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +3 -1
  294. package/project/.sdk/tm/ocaml/test/t_feature.ml +2 -2
  295. package/project/.sdk/tm/perl/core/context.pm +27 -0
  296. package/project/.sdk/tm/perl/core/error.pm +52 -5
  297. package/project/.sdk/tm/perl/feature/audit_feature.pm +2 -2
  298. package/project/.sdk/tm/perl/feature/cost_feature.pm +2 -2
  299. package/project/.sdk/tm/perl/feature/debug_feature.pm +17 -13
  300. package/project/.sdk/tm/perl/feature/log_feature.pm +3 -1
  301. package/project/.sdk/tm/perl/feature/proxy_feature.pm +21 -1
  302. package/project/.sdk/tm/perl/feature/secrets_feature.pm +20 -1
  303. package/project/.sdk/tm/perl/feature/telemetry_feature.pm +4 -2
  304. package/project/.sdk/tm/perl/t/feature.t +4 -2
  305. package/project/.sdk/tm/perl/utility/clean.pm +345 -1
  306. package/project/.sdk/tm/perl/utility/done.pm +24 -6
  307. package/project/.sdk/tm/perl/utility/make_error.pm +17 -4
  308. package/project/.sdk/tm/perl/utility/make_options.pm +33 -14
  309. package/project/.sdk/tm/php/core/Context.php +24 -1
  310. package/project/.sdk/tm/php/core/Error.php +34 -3
  311. package/project/.sdk/tm/php/core/UtilityType.php +4 -0
  312. package/project/.sdk/tm/php/feature/AuditFeature.php +2 -2
  313. package/project/.sdk/tm/php/feature/CostFeature.php +2 -2
  314. package/project/.sdk/tm/php/feature/DebugFeature.php +18 -9
  315. package/project/.sdk/tm/php/feature/LogFeature.php +5 -2
  316. package/project/.sdk/tm/php/feature/ProxyFeature.php +20 -1
  317. package/project/.sdk/tm/php/feature/SecretsFeature.php +18 -0
  318. package/project/.sdk/tm/php/feature/TelemetryFeature.php +4 -2
  319. package/project/.sdk/tm/php/test/FeatureTest.php +2 -2
  320. package/project/.sdk/tm/php/utility/Clean.php +438 -2
  321. package/project/.sdk/tm/php/utility/Done.php +14 -7
  322. package/project/.sdk/tm/php/utility/MakeError.php +9 -7
  323. package/project/.sdk/tm/php/utility/MakeOptions.php +62 -38
  324. package/project/.sdk/tm/php/utility/Register.php +2 -0
  325. package/project/.sdk/tm/py/pkg/core/context.py +17 -0
  326. package/project/.sdk/tm/py/pkg/core/error.py +42 -1
  327. package/project/.sdk/tm/py/pkg/core/utility_type.py +4 -0
  328. package/project/.sdk/tm/py/pkg/feature/audit_feature.py +2 -2
  329. package/project/.sdk/tm/py/pkg/feature/cost_feature.py +2 -2
  330. package/project/.sdk/tm/py/pkg/feature/debug_feature.py +17 -12
  331. package/project/.sdk/tm/py/pkg/feature/log_feature.py +2 -1
  332. package/project/.sdk/tm/py/pkg/feature/proxy_feature.py +18 -1
  333. package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +12 -0
  334. package/project/.sdk/tm/py/pkg/feature/telemetry_feature.py +4 -2
  335. package/project/.sdk/tm/py/pkg/utility/clean.py +311 -1
  336. package/project/.sdk/tm/py/pkg/utility/done.py +18 -5
  337. package/project/.sdk/tm/py/pkg/utility/make_error.py +9 -6
  338. package/project/.sdk/tm/py/pkg/utility/make_options.py +64 -25
  339. package/project/.sdk/tm/py/pkg/utility/make_response.py +19 -13
  340. package/project/.sdk/tm/py/pkg/utility/register.py +4 -2
  341. package/project/.sdk/tm/py/test/feature_harness.py +4 -0
  342. package/project/.sdk/tm/py/test/test_feature.py +2 -2
  343. package/project/.sdk/tm/py/test/test_primary_utility.py +1 -0
  344. package/project/.sdk/tm/rb/core/context.rb +28 -0
  345. package/project/.sdk/tm/rb/core/error.rb +30 -0
  346. package/project/.sdk/tm/rb/core/utility_type.rb +1 -1
  347. package/project/.sdk/tm/rb/feature/audit_feature.rb +2 -2
  348. package/project/.sdk/tm/rb/feature/cost_feature.rb +2 -2
  349. package/project/.sdk/tm/rb/feature/debug_feature.rb +15 -12
  350. package/project/.sdk/tm/rb/feature/log_feature.rb +3 -1
  351. package/project/.sdk/tm/rb/feature/proxy_feature.rb +25 -1
  352. package/project/.sdk/tm/rb/feature/secrets_feature.rb +17 -0
  353. package/project/.sdk/tm/rb/feature/telemetry_feature.rb +4 -2
  354. package/project/.sdk/tm/rb/test/feature_test.rb +4 -2
  355. package/project/.sdk/tm/rb/utility/clean.rb +312 -1
  356. package/project/.sdk/tm/rb/utility/done.rb +15 -5
  357. package/project/.sdk/tm/rb/utility/make_error.rb +13 -4
  358. package/project/.sdk/tm/rb/utility/make_options.rb +31 -12
  359. package/project/.sdk/tm/rb/utility/register.rb +2 -0
  360. package/project/.sdk/tm/rust/core/context.rs +55 -0
  361. package/project/.sdk/tm/rust/core/utility_type.rs +17 -0
  362. package/project/.sdk/tm/rust/feature/audit.rs +2 -0
  363. package/project/.sdk/tm/rust/feature/cost.rs +3 -2
  364. package/project/.sdk/tm/rust/feature/debug.rs +16 -16
  365. package/project/.sdk/tm/rust/feature/log.rs +42 -7
  366. package/project/.sdk/tm/rust/feature/proxy.rs +48 -2
  367. package/project/.sdk/tm/rust/feature/secrets.rs +12 -0
  368. package/project/.sdk/tm/rust/feature/telemetry.rs +2 -0
  369. package/project/.sdk/tm/rust/tests/feature_test.rs +2 -2
  370. package/project/.sdk/tm/rust/utility/clean.rs +446 -5
  371. package/project/.sdk/tm/rust/utility/done.rs +22 -12
  372. package/project/.sdk/tm/rust/utility/make_error.rs +4 -1
  373. package/project/.sdk/tm/rust/utility/make_options.rs +73 -19
  374. package/project/.sdk/tm/scala/Makefile +3 -1
  375. package/project/.sdk/tm/scala/core/Context.scala +16 -0
  376. package/project/.sdk/tm/scala/core/SdkClient.scala +14 -4
  377. package/project/.sdk/tm/scala/core/SdkError.scala +28 -0
  378. package/project/.sdk/tm/scala/core/Types.scala +3 -0
  379. package/project/.sdk/tm/scala/core/Utility.scala +2 -0
  380. package/project/.sdk/tm/scala/feature/AuditFeature.scala +16 -10
  381. package/project/.sdk/tm/scala/feature/CostFeature.scala +10 -5
  382. package/project/.sdk/tm/scala/feature/DebugFeature.scala +24 -21
  383. package/project/.sdk/tm/scala/feature/LogFeature.scala +9 -4
  384. package/project/.sdk/tm/scala/feature/ProxyFeature.scala +23 -2
  385. package/project/.sdk/tm/scala/feature/SecretsFeature.scala +14 -0
  386. package/project/.sdk/tm/scala/feature/TelemetryFeature.scala +9 -2
  387. package/project/.sdk/tm/scala/sdktest/SdkTestMain.scala +2 -2
  388. package/project/.sdk/tm/scala/utility/Make.scala +63 -20
  389. package/project/.sdk/tm/scala/utility/Misc.scala +358 -5
  390. package/project/.sdk/tm/scala/utility/Register.scala +1 -0
  391. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +29 -0
  392. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +2 -0
  393. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/AuditFeature.swift +10 -9
  394. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/CostFeature.swift +7 -5
  395. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/DebugFeature.swift +19 -15
  396. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/FeatureOptions.swift +16 -0
  397. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/LogFeature.swift +4 -1
  398. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/ProxyFeature.swift +20 -5
  399. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/SecretsFeature.swift +13 -0
  400. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TelemetryFeature.swift +4 -2
  401. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeError.swift +15 -5
  402. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +58 -19
  403. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +1 -0
  404. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +391 -4
  405. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/FeatureTest.swift +2 -2
  406. package/project/.sdk/tm/ts/src/Context.ts +5 -1
  407. package/project/.sdk/tm/ts/src/feature/audit/AuditFeature.ts +2 -2
  408. package/project/.sdk/tm/ts/src/feature/cost/CostFeature.ts +2 -2
  409. package/project/.sdk/tm/ts/src/feature/debug/DebugFeature.ts +13 -7
  410. package/project/.sdk/tm/ts/src/feature/log/LogFeature.ts +9 -5
  411. package/project/.sdk/tm/ts/src/feature/proxy/ProxyFeature.ts +19 -1
  412. package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +12 -0
  413. package/project/.sdk/tm/ts/src/feature/telemetry/TelemetryFeature.ts +4 -2
  414. package/project/.sdk/tm/ts/src/utility/CleanUtility.ts +287 -9
  415. package/project/.sdk/tm/ts/src/utility/DoneUtility.ts +18 -5
  416. package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +18 -8
  417. package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +38 -16
  418. package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -2
  419. package/project/.sdk/tm/ts/test/feature/harness.ts +11 -1
  420. package/project/.sdk/tm/ts/test/feature.test.ts +9 -2
  421. package/project/.sdk/tm/zig/core/context.zig +34 -0
  422. package/project/.sdk/tm/zig/core/error.zig +22 -1
  423. package/project/.sdk/tm/zig/core/utility.zig +403 -39
  424. package/project/.sdk/tm/zig/feature/audit.zig +4 -2
  425. package/project/.sdk/tm/zig/feature/cost.zig +3 -2
  426. package/project/.sdk/tm/zig/feature/debug.zig +20 -25
  427. package/project/.sdk/tm/zig/feature/log.zig +3 -1
  428. package/project/.sdk/tm/zig/feature/proxy.zig +47 -6
  429. package/project/.sdk/tm/zig/feature/secrets.zig +7 -0
  430. package/project/.sdk/tm/zig/feature/telemetry.zig +4 -2
  431. package/project/.sdk/tm/zig/test/feature_test.zig +2 -2
  432. package/project/sdkgen-package.json +1 -1
  433. package/src/action/copies.ts +219 -0
  434. package/src/action/doctor.ts +247 -21
  435. package/src/action/edition.ts +10 -2
  436. package/src/action/feature.ts +11 -2
  437. package/src/action/package.ts +31 -10
  438. package/src/action/remove.ts +4 -0
  439. package/src/action/resolve.ts +16 -3
  440. package/src/action/target.ts +10 -2
  441. package/src/helpers/naming.ts +1 -1
  442. package/src/sdkgen.ts +45 -5
@@ -0,0 +1,884 @@
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
+ const { target } = props
20
+ const javapackage: string = props.javapackage
21
+
22
+ const auth = {
23
+ suppressed: isAuthSuppressed(model),
24
+ where: resolveAuthIn(model),
25
+ name: 'header' === resolveAuthIn(model)
26
+ ? resolveAuthName(model).toLowerCase() : resolveAuthName(model),
27
+ basic: isHttpBasicAuth(model),
28
+ }
29
+
30
+ File({ name: 'CleanTest.' + target.ext }, () => {
31
+ Content(render(javapackage, model.const.Name + 'SDK', auth))
32
+ })
33
+ })
34
+
35
+
36
+ function render(jp: string, sdk: string, auth: {
37
+ suppressed: boolean, where: string, name: string, basic: boolean
38
+ }): string {
39
+ return `package ${jp}.sdktest;
40
+
41
+ import static org.junit.jupiter.api.Assertions.assertEquals;
42
+ import static org.junit.jupiter.api.Assertions.assertNotNull;
43
+ import static org.junit.jupiter.api.Assertions.assertTrue;
44
+ import static org.junit.jupiter.api.Assumptions.assumeTrue;
45
+
46
+ import java.io.PrintWriter;
47
+ import java.io.StringWriter;
48
+ import java.lang.reflect.Field;
49
+ import java.lang.reflect.InvocationTargetException;
50
+ import java.lang.reflect.Method;
51
+ import java.lang.reflect.Modifier;
52
+ import java.net.URLEncoder;
53
+ import java.nio.charset.StandardCharsets;
54
+ import java.util.ArrayList;
55
+ import java.util.Arrays;
56
+ import java.util.Base64;
57
+ import java.util.IdentityHashMap;
58
+ import java.util.Iterator;
59
+ import java.util.LinkedHashMap;
60
+ import java.util.List;
61
+ import java.util.Map;
62
+ import java.util.NoSuchElementException;
63
+ import java.util.TreeMap;
64
+ import java.util.function.BiFunction;
65
+ import java.util.function.Consumer;
66
+ import java.util.function.Function;
67
+ import java.util.function.Supplier;
68
+ import java.util.logging.Handler;
69
+ import java.util.logging.Level;
70
+ import java.util.logging.LogRecord;
71
+ import java.util.logging.Logger;
72
+
73
+ import org.junit.jupiter.api.Test;
74
+
75
+ import ${jp}.core.Config;
76
+ import ${jp}.core.Context;
77
+ import ${jp}.core.Entity;
78
+ import ${jp}.core.Helpers;
79
+ import ${jp}.core.${sdk};
80
+ import ${jp}.core.SdkEntity;
81
+ import ${jp}.core.SdkError;
82
+ import ${jp}.core.Utility;
83
+ import ${jp}.feature.BaseFeature;
84
+ import ${jp}.utility.struct.Struct;
85
+
86
+ @SuppressWarnings({"unchecked"})
87
+ public class CleanTest {
88
+
89
+ // Generated: the credential's wire placement is fixed when the SDK is built.
90
+ static final boolean AUTH_SUPPRESSED = ${auth.suppressed};
91
+ static final String AUTH_WHERE = ${JSON.stringify(auth.where)};
92
+ static final String AUTH_NAME = ${JSON.stringify(auth.name)};
93
+ static final boolean AUTH_BASIC = ${auth.basic};
94
+
95
+ static final String CANARY_APIKEY = "CANARY-APIKEY-k9x2m7q4p1";
96
+ static final String CANARY_SECRET = "CANARY-SECRET-w3e8r5t2y6";
97
+ static final String CANARY_HEADER = "CANARY-HEADER-z1x4c7v0b3";
98
+ static final String CANARY_VALUE = "CANARY-VALUE-n5m8b2v9c4";
99
+
100
+ static final String MASK = "[redacted]";
101
+
102
+ static final String NO_OP =
103
+ "no operation of this SDK completes against a plain 200; nothing to sweep";
104
+
105
+ // The logger the log feature builds when handed none.
106
+ static final String LOGGER_NAME = "${sdk}.log";
107
+
108
+ // Every form a canary can travel in.
109
+ static final List<String> FORMS = new ArrayList<>();
110
+
111
+ static {
112
+ for (String v : List.of(CANARY_APIKEY, CANARY_SECRET, CANARY_HEADER, CANARY_VALUE)) {
113
+ FORMS.add(v);
114
+ FORMS.add(base64(v));
115
+ FORMS.add(URLEncoder.encode(v, StandardCharsets.UTF_8));
116
+ }
117
+ FORMS.add(base64(CANARY_APIKEY + ":" + CANARY_SECRET));
118
+ }
119
+
120
+ static String base64(String s) {
121
+ return Base64.getEncoder().encodeToString(s.getBytes(StandardCharsets.UTF_8));
122
+ }
123
+
124
+ static final class Sink {
125
+ final String name;
126
+ final String text;
127
+
128
+ Sink(String name, String text) {
129
+ this.name = name;
130
+ this.text = text;
131
+ }
132
+ }
133
+
134
+ static Map<String, Object> jm(Object... kv) {
135
+ Map<String, Object> out = new LinkedHashMap<>();
136
+ for (int i = 0; i < kv.length - 1; i += 2) {
137
+ out.put(String.valueOf(kv[i]), kv[i + 1]);
138
+ }
139
+ return out;
140
+ }
141
+
142
+ // Header maps keep the caller's spelling; the assertion should not care.
143
+ static Object header(Object map, String name) {
144
+ Map<String, Object> m = Helpers.toMapAny(map);
145
+ if (m == null) {
146
+ return null;
147
+ }
148
+ for (Map.Entry<String, Object> e : m.entrySet()) {
149
+ if (e.getKey().equalsIgnoreCase(name)) {
150
+ return e.getValue();
151
+ }
152
+ }
153
+ return null;
154
+ }
155
+
156
+ static List<String> leaks(String text) {
157
+ List<String> out = new ArrayList<>();
158
+ for (String f : FORMS) {
159
+ if (text.contains(f)) {
160
+ out.add(f);
161
+ }
162
+ }
163
+ return out;
164
+ }
165
+
166
+ static boolean isFunction(Object v) {
167
+ return v instanceof Function || v instanceof Supplier || v instanceof Consumer
168
+ || v instanceof BiFunction || v instanceof Runnable || v instanceof Utility.CtxFn
169
+ || v instanceof Utility.FetcherFn || v.getClass().isSynthetic();
170
+ }
171
+
172
+ // The SDK's JSON emitter prints only maps, lists and scalars, so the
173
+ // sweep reads every other object the way a reflective serialiser would:
174
+ // its public fields, plus its own toString. This is what lets the negative
175
+ // control see the raw spec: with clean off the error carries the live Spec.
176
+ // A context is read as its serialised record, which is what it prints.
177
+ static Object plain(Object v, int depth, IdentityHashMap<Object, Boolean> seen) {
178
+ if (v == null || v instanceof String || v instanceof Number || v instanceof Boolean
179
+ || v instanceof Character || v instanceof Enum) {
180
+ return v;
181
+ }
182
+ if (isFunction(v)) {
183
+ return null;
184
+ }
185
+ if (32 <= depth || seen.containsKey(v)) {
186
+ return "[circular]";
187
+ }
188
+ seen.put(v, Boolean.TRUE);
189
+ try {
190
+ if (v instanceof Map) {
191
+ Map<String, Object> out = new LinkedHashMap<>();
192
+ for (Map.Entry<?, ?> e : ((Map<?, ?>) v).entrySet()) {
193
+ out.put(String.valueOf(e.getKey()), plain(e.getValue(), depth + 1, seen));
194
+ }
195
+ return out;
196
+ }
197
+ if (v instanceof List) {
198
+ List<Object> out = new ArrayList<>();
199
+ for (Object e : (List<Object>) v) {
200
+ out.add(plain(e, depth + 1, seen));
201
+ }
202
+ return out;
203
+ }
204
+ if (v instanceof Context) {
205
+ return plain(((Context) v).toMap(), depth + 1, seen);
206
+ }
207
+ Map<String, Object> out = new LinkedHashMap<>();
208
+ out.put("$string", String.valueOf(v));
209
+ if (v instanceof Throwable) {
210
+ out.put("$message", String.valueOf(((Throwable) v).getMessage()));
211
+ }
212
+ for (Field f : v.getClass().getFields()) {
213
+ if (Modifier.isStatic(f.getModifiers())) {
214
+ continue;
215
+ }
216
+ try {
217
+ out.put(f.getName(), plain(f.get(v), depth + 1, seen));
218
+ }
219
+ catch (ReflectiveOperationException | RuntimeException e) {
220
+ // unreadable field: nothing to sweep
221
+ }
222
+ }
223
+ return out;
224
+ }
225
+ finally {
226
+ seen.remove(v);
227
+ }
228
+ }
229
+
230
+ static String stack(Throwable err) {
231
+ StringWriter sw = new StringWriter();
232
+ err.printStackTrace(new PrintWriter(sw));
233
+ return sw.toString();
234
+ }
235
+
236
+ interface Text {
237
+ String get();
238
+ }
239
+
240
+ static void push(List<Sink> out, String name, Text fn) {
241
+ try {
242
+ out.add(new Sink(name, fn.get()));
243
+ }
244
+ catch (RuntimeException e) {
245
+ // a print that throws leaks nothing
246
+ }
247
+ }
248
+
249
+ // Every print of a value: the SDK's JSON, its stringify, the object's own
250
+ // toString; for an error also the message and the stack trace.
251
+ static void forms(List<Sink> out, String name, Object val) {
252
+ push(out, name + ":json", () -> Struct.jsonify(plain(val, 0, new IdentityHashMap<>())));
253
+ push(out, name + ":stringify", () -> Struct.stringify(plain(val, 0, new IdentityHashMap<>())));
254
+ push(out, name + ":string", () -> String.valueOf(val));
255
+ if (val instanceof Throwable) {
256
+ push(out, name + ":message", () -> String.valueOf(((Throwable) val).getMessage()));
257
+ push(out, name + ":stack", () -> stack((Throwable) val));
258
+ }
259
+ if (val instanceof SdkError) {
260
+ push(out, name + ":map", () -> Struct.jsonify(((SdkError) val).toMap()));
261
+ }
262
+ if (val instanceof Context) {
263
+ push(out, name + ":map", () -> Struct.jsonify(((Context) val).toMap()));
264
+ }
265
+ }
266
+
267
+ // A sink that is BOTH a Function and a Consumer: the option spec types a
268
+ // callback as a function, which the struct validator recognises only as
269
+ // Function or Supplier, while the feature reads its sink as a Consumer.
270
+ static final class Capture implements Consumer<Map<String, Object>>, Function<Object, Object> {
271
+ final List<Sink> sinks;
272
+ final String name;
273
+
274
+ Capture(List<Sink> sinks, String name) {
275
+ this.sinks = sinks;
276
+ this.name = name;
277
+ }
278
+
279
+ @Override
280
+ public void accept(Map<String, Object> rec) {
281
+ forms(this.sinks, this.name, rec);
282
+ }
283
+
284
+ @Override
285
+ public Object apply(Object rec) {
286
+ forms(this.sinks, this.name, rec);
287
+ return null;
288
+ }
289
+ }
290
+
291
+ // Captures the serialised context from inside the pipeline: what a hook
292
+ // author would hand to a logger. Public, as hook dispatch is reflective
293
+ // and skips a method it cannot access.
294
+ public static final class CaptureFeature extends BaseFeature {
295
+ final List<Sink> sinks;
296
+
297
+ CaptureFeature(List<Sink> sinks) {
298
+ super("capture", "0.0.1", true);
299
+ this.sinks = sinks;
300
+ }
301
+
302
+ @Override
303
+ public void preRequest(Context ctx) {
304
+ forms(this.sinks, "ctx@PreRequest", ctx);
305
+ }
306
+
307
+ @Override
308
+ public void preResponse(Context ctx) {
309
+ forms(this.sinks, "ctx@PreResponse", ctx);
310
+ }
311
+
312
+ @Override
313
+ public void preUnexpected(Context ctx) {
314
+ forms(this.sinks, "ctx@PreUnexpected", ctx);
315
+ }
316
+ }
317
+
318
+ // A feature that fails from inside the pipeline, quoting the request it
319
+ // saw in the code and the message. makeError cleans a failed stage, but
320
+ // PreUnexpected fires inside makeError: what a hook throws there does not
321
+ // pass through it.
322
+ public static final class ThrowFeature extends BaseFeature {
323
+ final boolean unexpected;
324
+
325
+ ThrowFeature(boolean unexpected) {
326
+ super("throwhook", "0.0.1", true);
327
+ this.unexpected = unexpected;
328
+ }
329
+
330
+ static RuntimeException saw(Context ctx) {
331
+ String saw = "hook saw " + Struct.jsonify(plain(ctx.spec, 0, new IdentityHashMap<>()));
332
+ return ctx.makeError(saw, saw);
333
+ }
334
+
335
+ @Override
336
+ public void preResponse(Context ctx) {
337
+ throw saw(ctx);
338
+ }
339
+
340
+ @Override
341
+ public void preUnexpected(Context ctx) {
342
+ if (this.unexpected) {
343
+ throw saw(ctx);
344
+ }
345
+ }
346
+ }
347
+
348
+ // A stream that fails while the caller iterates it, quoting a credential.
349
+ public static final class StreamThrowFeature extends BaseFeature {
350
+ StreamThrowFeature() {
351
+ super("streamthrow", "0.0.1", true);
352
+ }
353
+
354
+ @Override
355
+ public void preDone(Context ctx) {
356
+ ctx.result.stream = () -> new Iterator<Object>() {
357
+ @Override
358
+ public boolean hasNext() {
359
+ throw new RuntimeException("stream saw " + CANARY_APIKEY);
360
+ }
361
+
362
+ @Override
363
+ public Object next() {
364
+ throw new NoSuchElementException();
365
+ }
366
+ };
367
+ }
368
+ }
369
+
370
+ // A stream that succeeds, yielding the result's items.
371
+ public static final class StreamOkFeature extends BaseFeature {
372
+ StreamOkFeature() {
373
+ super("streamok", "0.0.1", true);
374
+ }
375
+
376
+ @Override
377
+ public void preDone(Context ctx) {
378
+ List<Object> items = new ArrayList<>();
379
+ if (ctx.result.resdata instanceof List) {
380
+ items.addAll((List<Object>) ctx.result.resdata);
381
+ }
382
+ else if (ctx.result.resdata != null) {
383
+ items.add(ctx.result.resdata);
384
+ }
385
+ ctx.result.stream = items::iterator;
386
+ }
387
+ }
388
+
389
+ static boolean hasFeature(String name) {
390
+ Map<String, Object> fm = Helpers.toMapAny(Config.makeConfig().get("feature"));
391
+ return fm != null && fm.get(name) != null;
392
+ }
393
+
394
+ static Map<String, Object> response(int status, Object data, Map<String, Object> headers) {
395
+ Map<String, Object> h = new LinkedHashMap<>();
396
+ h.put("content-type", "application/json");
397
+ if (headers != null) {
398
+ h.putAll(headers);
399
+ }
400
+ final Object body = data;
401
+ return jm(
402
+ "status", status,
403
+ "statusText", status < 400 ? "OK" : "ERR",
404
+ "headers", h,
405
+ "json", (Supplier<Object>) () -> body,
406
+ "body", Struct.jsonify(body));
407
+ }
408
+
409
+ static final class Scenario {
410
+ final String name;
411
+ final Utility.FetcherFn respond;
412
+
413
+ Scenario(String name, Utility.FetcherFn respond) {
414
+ this.name = name;
415
+ this.respond = respond;
416
+ }
417
+ }
418
+
419
+ static final List<Scenario> SCENARIOS = List.of(
420
+ new Scenario("ok", (ctx, url, fetchdef) ->
421
+ response(200, jm("id", "i1", "name", "n1"), jm("x-session-token", "RESP-TOKEN-a1b2c3d4e5"))),
422
+ new Scenario("notfound", (ctx, url, fetchdef) ->
423
+ response(404, jm("error", "no such record"), null)),
424
+ new Scenario("server", (ctx, url, fetchdef) ->
425
+ response(500, jm("error", "boom"), null)),
426
+ new Scenario("transport", (ctx, url, fetchdef) -> {
427
+ throw new RuntimeException("socket hang up (URL was: \\"" + url + "\\")");
428
+ }),
429
+ new Scenario("notjson", (ctx, url, fetchdef) -> jm(
430
+ "status", 200,
431
+ "statusText", "OK",
432
+ "headers", new LinkedHashMap<String, Object>(),
433
+ "json", (Supplier<Object>) () -> {
434
+ throw new RuntimeException("Unexpected token < in JSON");
435
+ },
436
+ "body", "<html>")));
437
+
438
+ static ${sdk} makeSdk(Scenario scenario, List<Sink> sinks, Map<String, Object> cleanopts,
439
+ BaseFeature... extra) {
440
+ Map<String, Object> feature = new LinkedHashMap<>();
441
+ if (hasFeature("log")) {
442
+ feature.put("log", jm("active", true));
443
+ }
444
+ if (hasFeature("debug")) {
445
+ feature.put("debug", jm("active", true, "onEntry", new Capture(sinks, "debug")));
446
+ }
447
+ if (hasFeature("audit")) {
448
+ feature.put("audit", jm("active", true, "sink", new Capture(sinks, "audit")));
449
+ }
450
+ if (hasFeature("telemetry")) {
451
+ feature.put("telemetry", jm("active", true, "exporter", new Capture(sinks, "telemetry")));
452
+ }
453
+ if (hasFeature("cost")) {
454
+ feature.put("cost", jm("active", true, "sink", new Capture(sinks, "cost")));
455
+ }
456
+ if (hasFeature("metrics")) {
457
+ feature.put("metrics", jm("active", true));
458
+ }
459
+ if (hasFeature("clienttrack")) {
460
+ feature.put("clienttrack", jm("active", true));
461
+ }
462
+
463
+ Map<String, Object> clean = jm("values", CANARY_VALUE);
464
+ if (cleanopts != null) {
465
+ clean.putAll(cleanopts);
466
+ }
467
+
468
+ List<Object> extend = new ArrayList<>();
469
+ extend.add(new CaptureFeature(sinks));
470
+ extend.addAll(Arrays.asList(extra));
471
+
472
+ Map<String, Object> opts = jm(
473
+ "apikey", CANARY_APIKEY,
474
+ "secret", CANARY_SECRET,
475
+ "headers", jm("X-Custom-Token", CANARY_HEADER),
476
+ "clean", clean,
477
+ "feature", feature,
478
+ "extend", extend,
479
+ "utility", jm("fetcher", scenario.respond));
480
+ return new ${sdk}(opts);
481
+ }
482
+
483
+ // Every log line the log feature emits, whichever level it chooses.
484
+ static Handler capture(List<Sink> sinks) {
485
+ Logger logger = Logger.getLogger(LOGGER_NAME);
486
+ Handler handler = new Handler() {
487
+ @Override
488
+ public void publish(LogRecord record) {
489
+ forms(sinks, "log." + record.getLevel().getName().toLowerCase(), record.getMessage());
490
+ }
491
+
492
+ @Override
493
+ public void flush() {}
494
+
495
+ @Override
496
+ public void close() {}
497
+ };
498
+ handler.setLevel(Level.ALL);
499
+ logger.addHandler(handler);
500
+ return handler;
501
+ }
502
+
503
+ static void release(Handler handler) {
504
+ Logger.getLogger(LOGGER_NAME).removeHandler(handler);
505
+ }
506
+
507
+ /** One discovered operation: the client accessor, the entity method, and its match. */
508
+ static final class Op {
509
+ final Method accessor;
510
+ final Method call;
511
+ final Map<String, Object> match;
512
+
513
+ Op(Method accessor, Method call, Map<String, Object> match) {
514
+ this.accessor = accessor;
515
+ this.call = call;
516
+ this.match = match;
517
+ }
518
+ }
519
+
520
+ static Object invoke(${sdk} client, Op op, Map<String, Object> ctrl) throws Exception {
521
+ Object ent = op.accessor.invoke(client, new Object[] {null});
522
+ try {
523
+ return op.call.invoke(ent, new LinkedHashMap<String, Object>(op.match), ctrl);
524
+ }
525
+ catch (InvocationTargetException ite) {
526
+ Throwable cause = ite.getCause();
527
+ if (cause instanceof Exception) {
528
+ throw (Exception) cause;
529
+ }
530
+ throw ite;
531
+ }
532
+ }
533
+
534
+ // Every path parameter an operation's points declare, filled in.
535
+ static Map<String, Object> filled(String entname, String opname) {
536
+ Map<String, Object> out = new LinkedHashMap<>();
537
+ Object points = Struct.getpath(Config.sharedConfig(),
538
+ List.of("entity", entname, "op", opname, "points"));
539
+ if (!(points instanceof List)) {
540
+ return out;
541
+ }
542
+ for (Object point : (List<Object>) points) {
543
+ Object params = Struct.getpath(point, List.of("args", "params"));
544
+ if (params instanceof List) {
545
+ for (Object param : (List<Object>) params) {
546
+ Object name = Struct.getprop(param, "name");
547
+ if (name instanceof String) {
548
+ out.put((String) name, "p1");
549
+ }
550
+ }
551
+ }
552
+ }
553
+ return out;
554
+ }
555
+
556
+ // The first operation that completes against a plain 200: with no
557
+ // arguments, else with every path parameter its points declare filled in.
558
+ static Op usableOp() {
559
+ Utility.FetcherFn ok = (ctx, url, fetchdef) -> response(200, jm("id", "i1"), null);
560
+ Map<String, Object> plainOpts = jm("apikey", CANARY_APIKEY, "utility", jm("fetcher", ok));
561
+
562
+ Map<String, Method> accessors = new TreeMap<>();
563
+ ${sdk} probe = new ${sdk}(plainOpts);
564
+ for (Method m : probe.getClass().getMethods()) {
565
+ if (1 != m.getParameterCount() || !Map.class.isAssignableFrom(m.getParameterTypes()[0])) {
566
+ continue;
567
+ }
568
+ if (!Entity.class.isAssignableFrom(m.getReturnType())) {
569
+ continue;
570
+ }
571
+ String entname;
572
+ try {
573
+ entname = ((Entity) m.invoke(probe, new Object[] {null})).getName();
574
+ }
575
+ catch (Exception e) {
576
+ continue;
577
+ }
578
+ if (null != entname && !entname.isEmpty()) {
579
+ accessors.put(entname, m);
580
+ }
581
+ }
582
+
583
+ for (Map.Entry<String, Method> e : accessors.entrySet()) {
584
+ Object ent;
585
+ try {
586
+ ent = e.getValue().invoke(probe, new Object[] {null});
587
+ }
588
+ catch (Exception ex) {
589
+ continue;
590
+ }
591
+ for (String opname : List.of("list", "load", "create", "update", "remove")) {
592
+ Method call;
593
+ try {
594
+ call = ent.getClass().getMethod(opname, Map.class, Map.class);
595
+ }
596
+ catch (NoSuchMethodException ex) {
597
+ continue;
598
+ }
599
+ List<Map<String, Object>> matches =
600
+ List.of(new LinkedHashMap<>(), filled(e.getKey(), opname));
601
+ for (Map<String, Object> match : matches) {
602
+ Op op = new Op(e.getValue(), call, match);
603
+ try {
604
+ invoke(new ${sdk}(plainOpts), op, new LinkedHashMap<>());
605
+ return op;
606
+ }
607
+ catch (Exception ex) {
608
+ continue;
609
+ }
610
+ }
611
+ }
612
+ }
613
+ return null;
614
+ }
615
+
616
+ // Nothing usable is a visible skip; the lane then misses the swept line.
617
+ static Op usableOrSkip() {
618
+ Op op = usableOp();
619
+ if (op == null) {
620
+ System.out.println("clean: skipped: " + NO_OP);
621
+ }
622
+ assumeTrue(op != null, NO_OP);
623
+ return op;
624
+ }
625
+
626
+ static Exception drive(${sdk} sdk, Op op, Map<String, Object> ctrl, List<Sink> sinks) {
627
+ // A caller may keep the record it passed rather than read ctrl's entry.
628
+ Object held = ctrl.get("explain");
629
+ Object out = null;
630
+ Exception err = null;
631
+ try {
632
+ out = invoke(sdk, op, ctrl);
633
+ }
634
+ catch (Exception e) {
635
+ err = e;
636
+ }
637
+ if (err != null) {
638
+ forms(sinks, "error", err);
639
+ }
640
+ if (out != null) {
641
+ forms(sinks, "result", out);
642
+ }
643
+ if (ctrl.get("explain") != null) {
644
+ forms(sinks, "explain", ctrl.get("explain"));
645
+ }
646
+ if (held != null && held != ctrl.get("explain")) {
647
+ forms(sinks, "explain:held", held);
648
+ }
649
+ return err;
650
+ }
651
+
652
+ @Test
653
+ public void noCredentialLeavesTheSdkInAnyForm() throws Exception {
654
+ Op op = usableOrSkip();
655
+
656
+ List<Sink> sinks = new ArrayList<>();
657
+ Map<String, Exception> errors = new LinkedHashMap<>();
658
+ Map<String, Map<String, Object>> explains = new LinkedHashMap<>();
659
+ Object numbered = null;
660
+ Object named = null;
661
+
662
+ Handler handler = capture(sinks);
663
+ try {
664
+ for (Scenario scenario : SCENARIOS) {
665
+ for (String variant : List.of("throw", "explain", "nothrow")) {
666
+ Map<String, Object> ctrl = new LinkedHashMap<>();
667
+ if (!"throw".equals(variant)) {
668
+ ctrl.put("explain", new LinkedHashMap<String, Object>());
669
+ }
670
+ if ("nothrow".equals(variant)) {
671
+ ctrl.put("throw", false);
672
+ }
673
+ ${sdk} sdk = makeSdk(scenario, sinks, null);
674
+ Exception err = drive(sdk, op, ctrl, sinks);
675
+ String key = scenario.name + "/" + variant;
676
+ if (err != null) {
677
+ errors.put(key, err);
678
+ }
679
+ if (ctrl.get("explain") != null) {
680
+ explains.put(key, (Map<String, Object>) ctrl.get("explain"));
681
+ }
682
+ forms(sinks, "sdk", sdk);
683
+ }
684
+ }
685
+
686
+ // No clean option at all: the schema defaults still apply.
687
+ ${sdk} bare = new ${sdk}(jm(
688
+ "apikey", CANARY_APIKEY,
689
+ "secret", CANARY_SECRET,
690
+ "headers", jm("X-Custom-Token", CANARY_HEADER),
691
+ "utility", jm("fetcher", SCENARIOS.get(1).respond)));
692
+ assertNotNull(drive(bare, op, new LinkedHashMap<>(), sinks), "the 404 should fail");
693
+
694
+ // A credential mistyped as a map. The java validator collects its
695
+ // errors and substitutes the default rather than rejecting, so there
696
+ // is no rejection to sweep: sweep the client, and what clean makes of
697
+ // the value should anything quote it.
698
+ try {
699
+ ${sdk} mistyped = new ${sdk}(jm(
700
+ "apikey", jm("value", CANARY_APIKEY), "clean", jm("values", CANARY_VALUE)));
701
+ forms(sinks, "mistyped", mistyped);
702
+ forms(sinks, "mistyped:quoted", mistyped.getUtility().clean.apply(
703
+ mistyped.getRootCtx(), "found map: " + CANARY_APIKEY));
704
+ }
705
+ catch (RuntimeException e) {
706
+ forms(sinks, "mistyped:rejected", e);
707
+ }
708
+
709
+ // A number is registered as the text a message quotes it in.
710
+ ${sdk} numeric = new ${sdk}(jm("apikey", 918273645));
711
+ numbered = numeric.getUtility().clean.apply(numeric.getRootCtx(), "found 918273645");
712
+
713
+ for (boolean unexpected : new boolean[] {false, true}) {
714
+ ${sdk} hooked = makeSdk(SCENARIOS.get(0), sinks, null, new ThrowFeature(unexpected));
715
+ assertNotNull(drive(hooked, op, jm("explain", new LinkedHashMap<String, Object>()), sinks),
716
+ "the throwing hook should fail the operation");
717
+ }
718
+
719
+ // Iterating a stream runs inside the same catch path as the operation,
720
+ // and the explain record the caller passed is cleaned however it ends.
721
+ Map<String, BaseFeature[]> streams = new LinkedHashMap<>();
722
+ streams.put("stream", new BaseFeature[] {new StreamThrowFeature()});
723
+ streams.put("stream-ok", new BaseFeature[] {new StreamOkFeature()});
724
+ streams.put("stream-plain", new BaseFeature[] {});
725
+ for (Map.Entry<String, BaseFeature[]> entry : streams.entrySet()) {
726
+ String name = entry.getKey();
727
+ SdkEntity streamed = (SdkEntity) op.accessor.invoke(
728
+ makeSdk(SCENARIOS.get(0), sinks, null, entry.getValue()), new Object[] {null});
729
+ Map<String, Object> explain = new LinkedHashMap<>();
730
+ RuntimeException streamerr = null;
731
+ try {
732
+ streamed.stream(op.call.getName(), jm("reqmatch", new LinkedHashMap<>(op.match)),
733
+ jm("ctrl", jm("explain", explain))).forEach(item -> { });
734
+ }
735
+ catch (RuntimeException e) {
736
+ streamerr = e;
737
+ }
738
+ assertEquals("stream".equals(name), streamerr != null, name + ": only the failing stream throws");
739
+ if (streamerr != null) {
740
+ forms(sinks, name, streamerr);
741
+ }
742
+ assertTrue(!explain.isEmpty(), name + ": the explain record was not filled");
743
+ forms(sinks, name + ":explain", explain);
744
+ }
745
+
746
+ // The raw path returns its failure rather than throwing it.
747
+ Map<String, Object> raw = makeSdk(SCENARIOS.get(3), sinks, null).direct(jm("path", "raw"));
748
+ assertTrue(Boolean.FALSE.equals(raw.get("ok")) && raw.get("err") instanceof Throwable,
749
+ "a transport failure should fail direct() with an error");
750
+ forms(sinks, "direct", raw.get("err"));
751
+
752
+ // A registered value used as a property name is masked; names that
753
+ // mask alike are kept apart.
754
+ ${sdk} probe = makeSdk(SCENARIOS.get(0), sinks, null);
755
+ named = probe.getUtility().clean.apply(probe.getRootCtx(),
756
+ jm(CANARY_VALUE, 1, CANARY_HEADER, 2, "plain", 3));
757
+ forms(sinks, "named", named);
758
+ }
759
+ finally {
760
+ release(handler);
761
+ }
762
+
763
+ List<String> leaked = new ArrayList<>();
764
+ for (Sink s : sinks) {
765
+ List<String> found = leaks(s.text);
766
+ if (!found.isEmpty()) {
767
+ leaked.add(s.name + " [" + String.join(", ", found) + "]");
768
+ }
769
+ }
770
+
771
+ System.out.println("clean: swept " + sinks.size() + " surface(s), " + leaked.size() + " leak(s)");
772
+
773
+ assertEquals(0, leaked.size(), "credential leaked through: " + String.join("; ", leaked));
774
+
775
+ assertEquals("found " + MASK, numbered);
776
+ assertEquals(jm(MASK, 1, MASK + "#1", 2, "plain", 3), named);
777
+
778
+ // The positive half: the slot the credential travelled in is masked,
779
+ // and an unregistered token in a response header is masked by name.
780
+ Exception notfound = errors.get("notfound/throw");
781
+ assertNotNull(notfound, "the 404 scenario must throw");
782
+ assertTrue(notfound instanceof SdkError, "the 404 scenario must throw the SDK error: " + notfound);
783
+ SdkError sdkerr = (SdkError) notfound;
784
+ assertEquals(404, sdkerr.status);
785
+ Map<String, Object> spec = Helpers.toMapAny(sdkerr.spec);
786
+ assertNotNull(spec, "the error should carry the cleaned spec as a map");
787
+ if (!AUTH_SUPPRESSED) {
788
+ if ("query".equals(AUTH_WHERE)) {
789
+ assertEquals(MASK, header(spec.get("query"), AUTH_NAME));
790
+ }
791
+ else if ("cookie".equals(AUTH_WHERE)) {
792
+ String cookie = String.valueOf(header(spec.get("headers"), "cookie"));
793
+ assertTrue(cookie.contains(MASK), "cookie: " + cookie);
794
+ }
795
+ else {
796
+ String cred = String.valueOf(header(spec.get("headers"), AUTH_NAME));
797
+ assertTrue(cred.endsWith(MASK), AUTH_NAME + ": " + cred);
798
+ }
799
+ }
800
+ assertEquals(MASK, header(spec.get("headers"), "x-custom-token"));
801
+
802
+ Map<String, Object> explained = explains.get("ok/explain");
803
+ assertNotNull(explained);
804
+ Map<String, Object> result = Helpers.toMapAny(explained.get("result"));
805
+ assertNotNull(result, "the explain record should carry the result");
806
+ assertEquals(MASK, header(result.get("headers"), "x-session-token"));
807
+ }
808
+
809
+ @Test
810
+ public void theSweepCanSeeALeakCleanSwitchedOffShowsTheCredential() {
811
+ Op op = usableOrSkip();
812
+
813
+ List<Sink> sinks = new ArrayList<>();
814
+ ${sdk} sdk = makeSdk(SCENARIOS.get(1), sinks, jm("active", false));
815
+ Exception err = drive(sdk, op, new LinkedHashMap<>(), sinks);
816
+ assertNotNull(err);
817
+
818
+ // Explaining a failure must not cost it its error.
819
+ Exception explained = drive(makeSdk(SCENARIOS.get(1), new ArrayList<>(), jm("active", false)), op,
820
+ jm("explain", new LinkedHashMap<String, Object>()), new ArrayList<>());
821
+ assertEquals(err.getMessage(), explained == null ? null : explained.getMessage(),
822
+ "with clean off, explain lost the error");
823
+
824
+ int leaked = 0;
825
+ for (Sink s : sinks) {
826
+ if (!leaks(s.text).isEmpty()) {
827
+ leaked++;
828
+ }
829
+ }
830
+ assertTrue(0 < leaked, "with clean off, nothing showed the canary: the sweep is blind");
831
+
832
+ if (!AUTH_SUPPRESSED) {
833
+ assertTrue(err instanceof SdkError, "expected the SDK error: " + err);
834
+ String text = Struct.jsonify(plain(((SdkError) err).spec, 0, new IdentityHashMap<>()));
835
+ assertTrue(text.contains(CANARY_APIKEY)
836
+ || text.contains(base64(CANARY_APIKEY + ":" + CANARY_SECRET)),
837
+ "the raw spec should carry the credential when clean is off");
838
+ }
839
+ }
840
+
841
+ // An entity block, of per-entity settings or seeded records keyed by
842
+ // entity name and id, is not read at all.
843
+ @Test
844
+ public void aFeatureNameDoesNotMakeItsSettingsSecret() {
845
+ ${sdk} sdk = new ${sdk}(jm(
846
+ "apikey", CANARY_APIKEY,
847
+ "feature", jm(
848
+ "secrets", jm("active", false, "kind", "SETTING-KIND-4829", "token", CANARY_SECRET),
849
+ "test", jm("active", false, "entity",
850
+ jm("zztoken", jm("ZZTOKEN01", jm("note", "PLAINRECORD-t5r3e1w9"))))),
851
+ "entity", jm("zztoken", jm("alias", jm("zzkey", "PLAINALIAS-m2n4b6v8")))));
852
+ Context root = sdk.getRootCtx();
853
+ assertEquals("SETTING-KIND-4829 " + MASK,
854
+ sdk.getUtility().clean.apply(root, "SETTING-KIND-4829 " + CANARY_SECRET));
855
+ assertEquals("record PLAINRECORD-t5r3e1w9",
856
+ sdk.getUtility().clean.apply(root, "record PLAINRECORD-t5r3e1w9"));
857
+ assertEquals("alias PLAINALIAS-m2n4b6v8",
858
+ sdk.getUtility().clean.apply(root, "alias PLAINALIAS-m2n4b6v8"));
859
+ }
860
+
861
+ @Test
862
+ public void theGeneratedConfigsOwnCleanBlockIsHonoured() {
863
+ Map<String, Object> cfgclean = jm("keys", "zzsens", "values", "CONFIG-SEEDED-1");
864
+ Utility utility = new Utility();
865
+ Context ctx = utility.makeContext.apply(jm(
866
+ "utility", utility,
867
+ "config", jm("options", jm("clean", cfgclean)),
868
+ "options", jm("clean", jm("values", "CALLER-SEEDED-2"))), null);
869
+ ctx.options = utility.makeOptions.apply(ctx);
870
+
871
+ assertEquals("a " + MASK + " b " + MASK,
872
+ utility.clean.apply(ctx, "a CONFIG-SEEDED-1 b CALLER-SEEDED-2"));
873
+ assertEquals(jm("my_zzsens", MASK, "other", "y"),
874
+ utility.clean.apply(ctx, jm("my_zzsens", "x", "other", "y")));
875
+ assertEquals("CONFIG-SEEDED-1", cfgclean.get("values"));
876
+ }
877
+ }
878
+ `
879
+ }
880
+
881
+
882
+ export {
883
+ TestClean
884
+ }