@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
@@ -3,13 +3,357 @@
3
3
  use strict;
4
4
  use warnings;
5
5
 
6
+ use File::Basename ();
7
+ use Cwd ();
8
+ use Scalar::Util ();
9
+ use MIME::Base64 ();
10
+
11
+ my $__dir;
12
+ BEGIN { $__dir = File::Basename::dirname(Cwd::abs_path(__FILE__)) }
13
+ require(Cwd::abs_path("$__dir/../lib/Voxgig/Struct.pm"));
14
+ require(Cwd::abs_path("$__dir/../core/helpers.pm"));
15
+ require(Cwd::abs_path("$__dir/../schema.pm"));
16
+
17
+ # Everything that leaves the pipeline passes through clean: the error, the
18
+ # explain record, the serialised context, and whatever a feature emits.
19
+ # Two layers: every registered secret VALUE (and its encoded forms) is
20
+ # replaced wherever it appears in a string, and every value under a
21
+ # sensitive KEY name is masked whatever it holds. Inside the pipeline data
22
+ # stays raw, so a hook can still read the header it must add to.
23
+ package ProjectNameCleanSupport;
24
+
25
+ my $MAXDEPTH = 32;
26
+ my $CIRCULAR = '[circular]';
27
+
28
+ # Marks a value the copy omits (a coderef), as ts omits `undefined`.
29
+ my $DROP = \'drop';
30
+
31
+ sub _dropped {
32
+ my ($v) = @_;
33
+ return ref $v && Scalar::Util::refaddr($v) == Scalar::Util::refaddr($DROP) ? 1 : 0;
34
+ }
35
+
36
+ sub normkey {
37
+ my ($key) = @_;
38
+ my $k = lc("$key");
39
+ $k =~ s/[-_]//g;
40
+ return $k;
41
+ }
42
+
43
+ sub splitkeys {
44
+ my ($keys) = @_;
45
+ return [] unless defined $keys && !ref $keys;
46
+ return [ grep { '' ne $_ } map { normkey($_) } split /\s*,\s*/, "$keys" ];
47
+ }
48
+
49
+ # The comma-separated literal values a caller registers; a list is taken
50
+ # as-is for a caller that has one.
51
+ sub splitvalues {
52
+ my ($values) = @_;
53
+ if (Voxgig::Struct::islist($values)) {
54
+ return [ grep { defined $_ && !ref $_ } @$values ];
55
+ }
56
+ return [] unless defined $values && !ref $values;
57
+ return [ grep { '' ne $_ } split /\s*,\s*/, "$values" ];
58
+ }
59
+
60
+ # The spec carries numbers as strings, so every target reads it alike.
61
+ sub count {
62
+ my ($val, $dflt) = @_;
63
+ return $dflt unless defined $val && !ref $val && Scalar::Util::looks_like_number($val);
64
+ my $n = int($val);
65
+ return $n < 0 ? $dflt : $n;
66
+ }
67
+
68
+ # The derived block make_options builds; a context without options
69
+ # (make_error is reached with a bare one) falls back to the schema
70
+ # defaults, so nothing leaves raw for want of a constructor. A plain hash
71
+ # stands in for a context before one exists (make_options).
72
+ sub config {
73
+ my ($ctx) = @_;
74
+ my $opts = (defined $ctx && ref $ctx && (Scalar::Util::reftype($ctx) // '') eq 'HASH')
75
+ ? $ctx->{options} : undef;
76
+ my $derived = Voxgig::Struct::ismap($opts) ? $opts->{__derived__} : undef;
77
+ my $cfg = Voxgig::Struct::ismap($derived) ? $derived->{clean} : undef;
78
+ return $cfg if Voxgig::Struct::ismap($cfg) && Voxgig::Struct::islist($cfg->{values});
79
+ return make_config(ProjectNameSchema::optspec()->{clean});
80
+ }
81
+
82
+ sub make_config {
83
+ my ($cleanopts) = @_;
84
+ my $o = Voxgig::Struct::ismap($cleanopts) ? $cleanopts : {};
85
+ my $min = count($o->{min}, 4);
86
+ return {
87
+ 'active' => ProjectNameHelpers::is_false($o->{active}) ? 0 : 1,
88
+ 'keys' => splitkeys($o->{keys}),
89
+ 'values' => [],
90
+ 'mask' => (defined $o->{mask} && !ref $o->{mask}) ? "$o->{mask}" : '[redacted]',
91
+ 'hint' => count($o->{hint}, 0),
92
+ 'min' => ($min < 1 ? 1 : $min),
93
+ };
94
+ }
95
+
96
+ # encodeURIComponent, byte for byte: the form a query credential travels in.
97
+ sub pct {
98
+ my ($value) = @_;
99
+ my $b = "$value";
100
+ utf8::encode($b) if utf8::is_utf8($b);
101
+ $b =~ s/([^A-Za-z0-9\-_.!~*'()])/sprintf('%%%02X', ord($1))/ge;
102
+ return $b;
103
+ }
104
+
105
+ # The JSON string escape, as a JSON dump would write the value.
106
+ sub jsonesc {
107
+ my ($value) = @_;
108
+ my $s = "$value";
109
+ $s =~ s/\\/\\\\/g;
110
+ $s =~ s/"/\\"/g;
111
+ $s =~ s/\n/\\n/g;
112
+ $s =~ s/\r/\\r/g;
113
+ $s =~ s/\t/\\t/g;
114
+ $s =~ s/([\x00-\x1f])/sprintf('\\u%04x', ord($1))/ge;
115
+ return $s;
116
+ }
117
+
118
+ # The encoded forms a value travels in: Basic and Bearer both carry base64,
119
+ # a query credential is percent-encoded, and a JSON dump escapes it.
120
+ sub forms {
121
+ my ($value) = @_;
122
+ my @out = ("$value");
123
+ my $add = sub {
124
+ my ($s) = @_;
125
+ push @out, $s if defined $s && '' ne $s && !grep { $_ eq $s } @out;
126
+ };
127
+ my $b = "$value";
128
+ utf8::encode($b) if utf8::is_utf8($b);
129
+ $add->(MIME::Base64::encode_base64($b, ''));
130
+ $add->(pct($value));
131
+ $add->(jsonesc($value));
132
+ return @out;
133
+ }
134
+
135
+ # Register a secret value. Idempotent; shorter than `min` is not a secret
136
+ # the SDK can mask without blanking ordinary text.
137
+ sub add {
138
+ my ($ctx, $value) = @_;
139
+ my $cfg = config($ctx);
140
+ return unless defined $value && !ref $value && length("$value") >= $cfg->{min};
141
+ my $values = $cfg->{values};
142
+ my $changed = 0;
143
+ for my $form (forms($value)) {
144
+ next if length($form) < $cfg->{min} || grep { $_ eq $form } @$values;
145
+ push @$values, $form;
146
+ $changed = 1;
147
+ }
148
+ @$values = sort { length($b) <=> length($a) } @$values if $changed;
149
+ return;
150
+ }
151
+
152
+ sub mask_value {
153
+ my ($cfg, $value) = @_;
154
+ my $hint = $cfg->{hint};
155
+ return $cfg->{mask} . substr($value, -$hint) if $hint > 0 && length($value) > 2 * $hint;
156
+ return $cfg->{mask};
157
+ }
158
+
159
+ # The scalar comes back untouched when no value matches, so a number stays
160
+ # a number.
161
+ sub clean_string {
162
+ my ($cfg, $text) = @_;
163
+ my $out = $text;
164
+ my $hit = 0;
165
+ for my $value (@{ $cfg->{values} }) {
166
+ next if index("$out", $value) < 0;
167
+ my $masked = mask_value($cfg, $value);
168
+ my $q = quotemeta $value;
169
+ $out = "$out";
170
+ $out =~ s/$q/$masked/g;
171
+ $hit = 1;
172
+ }
173
+ return $hit ? $out : $text;
174
+ }
175
+
176
+ sub sensitive_key {
177
+ my ($cfg, $key) = @_;
178
+ return 0 unless defined $key && !ref $key;
179
+ my $nk = normkey($key);
180
+ for my $k (@{ $cfg->{keys} }) {
181
+ return 1 if index($nk, $k) >= 0;
182
+ }
183
+ return 0;
184
+ }
185
+
186
+ # A plain-data copy of what is about to leave: TO_JSON is honoured (an
187
+ # entity gives its data, a context its record), coderefs are dropped,
188
+ # cycles are cut, and no live object is shared with the copy - masking the
189
+ # copy must never mask the pipeline's own spec. Any other blessed hash
190
+ # copies as its fields; the error keeps its context out of them.
191
+ sub snapshot {
192
+ my ($cfg, $val, $key, $depth, $seen) = @_;
193
+ return $val unless defined $val;
194
+
195
+ if (!ref $val) {
196
+ return sensitive_key($cfg, $key) ? mask_value($cfg, "$val") : clean_string($cfg, $val);
197
+ }
198
+
199
+ if (Voxgig::Struct::is_jbool($val) || Voxgig::Struct::is_jnull($val) || Voxgig::Struct::is_none($val)) {
200
+ return sensitive_key($cfg, $key) ? $cfg->{mask} : $val;
201
+ }
202
+
203
+ my $type = Scalar::Util::reftype($val) // '';
204
+ return $DROP unless 'HASH' eq $type || 'ARRAY' eq $type;
205
+
206
+ my $addr = Scalar::Util::refaddr($val);
207
+ return $CIRCULAR if $depth >= $MAXDEPTH || $seen->{$addr};
208
+ return $cfg->{mask} if sensitive_key($cfg, $key);
209
+
210
+ $seen->{$addr} = 1;
211
+ my $out;
212
+ if ('ARRAY' eq $type) {
213
+ $out = [];
214
+ for (my $i = 0; $i < @$val; $i++) {
215
+ my $v = snapshot($cfg, $val->[$i], "$i", $depth + 1, $seen);
216
+ push @$out, $v unless _dropped($v);
217
+ }
218
+ }
219
+ elsif (Scalar::Util::blessed($val) && $val->isa('ProjectNameError')) {
220
+ $out = plain($cfg, $val, $depth, $seen);
221
+ $out->{message} = clean_string($cfg, defined $val->{msg} ? "$val->{msg}" : '');
222
+ }
223
+ elsif (Scalar::Util::blessed($val) && $val->can('TO_JSON')) {
224
+ my $json = eval { $val->TO_JSON };
225
+ $out = $@ ? plain($cfg, $val, $depth, $seen) : snapshot($cfg, $json, $key, $depth + 1, $seen);
226
+ }
227
+ else {
228
+ $out = plain($cfg, $val, $depth, $seen);
229
+ }
230
+ delete $seen->{$addr};
231
+ return $out;
232
+ }
233
+
234
+ sub plain {
235
+ my ($cfg, $val, $depth, $seen) = @_;
236
+ my $out = {};
237
+ for my $k (sort keys %$val) {
238
+ my $v = snapshot($cfg, $val->{$k}, $k, $depth + 1, $seen);
239
+ $out->{ clean_name($cfg, $out, $k) } = $v unless _dropped($v);
240
+ }
241
+ return $out;
242
+ }
243
+
244
+ # A registered value used as a property name is masked like any other
245
+ # string; names that mask alike take a counter, so none is lost. Callers
246
+ # visit keys sorted, so the counters are stable.
247
+ sub clean_name {
248
+ my ($cfg, $out, $key) = @_;
249
+ my $name = clean_string($cfg, $key);
250
+ return $name if $name eq $key || !exists $out->{$name};
251
+ my $i = 1;
252
+ $i++ while exists $out->{"$name#$i"};
253
+ return "$name#$i";
254
+ }
255
+
256
+ # Clean a value on its way out. A string is redacted; an SDK error is
257
+ # redacted IN PLACE (it is about to be thrown, and its identity matters to
258
+ # the caller); another blessed object is not this SDK's to rewrite and comes
259
+ # back as it is; anything else comes back as a masked plain-data copy.
260
+ sub clean {
261
+ my ($ctx, $val) = @_;
262
+ my $cfg = config($ctx);
263
+
264
+ return $val unless $cfg->{active};
265
+ return $val unless defined $val;
266
+ return clean_string($cfg, $val) unless ref $val;
267
+
268
+ if (Scalar::Util::blessed($val)) {
269
+ return $val unless $val->isa('ProjectNameError');
270
+ $val->{msg} = clean_string($cfg, "$val->{msg}") if defined $val->{msg};
271
+ for my $k (sort keys %$val) {
272
+ next if 'msg' eq $k;
273
+ my $v = $val->{$k};
274
+ if (defined $v && !ref $v) {
275
+ $v = sensitive_key($cfg, $k) ? mask_value($cfg, "$v") : clean_string($cfg, $v);
276
+ }
277
+ elsif (ref $v && (Scalar::Util::reftype($v) // '') =~ /\A(?:HASH|ARRAY)\z/) {
278
+ $v = snapshot($cfg, $v, $k, 1, {});
279
+ }
280
+ my $name = clean_string($cfg, $k);
281
+ delete $val->{$k} if $name ne $k;
282
+ $val->{ $name eq $k ? $k : clean_name($cfg, $val, $k) } = $v;
283
+ }
284
+ return $val;
285
+ }
286
+
287
+ my $out = snapshot($cfg, $val, undef, 0, {});
288
+ return _dropped($out) ? undef : $out;
289
+ }
290
+
291
+ # Every scalar under a sensitive name, at any depth and of any shape: a
292
+ # credential mistyped as a map or a number is still a credential, and the
293
+ # validation error that rejects it quotes it.
294
+ sub add_sensitive {
295
+ my ($ctx, $val, $under, $depth, $seen) = @_;
296
+ $depth //= 0;
297
+ $seen //= {};
298
+ return if !defined $val || $depth >= $MAXDEPTH;
299
+ if (!ref $val) {
300
+ add($ctx, "$val") if $under;
301
+ return;
302
+ }
303
+ my $type = Scalar::Util::reftype($val) // '';
304
+ return unless 'HASH' eq $type || 'ARRAY' eq $type;
305
+ return if $seen->{ Scalar::Util::refaddr($val) }++;
306
+ if ('HASH' eq $type) {
307
+ add_sensitive($ctx, $val->{$_}, $under || key($ctx, $_), $depth + 1, $seen) for keys %$val;
308
+ }
309
+ else {
310
+ add_sensitive($ctx, $_, $under, $depth + 1, $seen) for @$val;
311
+ }
312
+ return;
313
+ }
314
+
315
+ # A feature's name is not a field name: only the sensitive names inside its
316
+ # settings count, so `secrets` does not make every setting a secret. Entity
317
+ # blocks (per-entity settings, seeded records) hold no credential.
318
+ sub add_options {
319
+ my ($ctx, $opts) = @_;
320
+ my %scan = %$opts;
321
+ my $feature = delete $scan{feature};
322
+ delete $scan{entity};
323
+ $scan{test} = no_entity($scan{test}) if exists $scan{test};
324
+ add_sensitive($ctx, \%scan);
325
+ my @blocks = Voxgig::Struct::ismap($feature) ? values %$feature
326
+ : Voxgig::Struct::islist($feature) ? @$feature : ($feature);
327
+ add_sensitive($ctx, no_entity($_)) for @blocks;
328
+ return;
329
+ }
330
+
331
+ sub no_entity {
332
+ my ($block) = @_;
333
+ return $block unless Voxgig::Struct::ismap($block);
334
+ my %copy = %$block;
335
+ delete $copy{entity};
336
+ return \%copy;
337
+ }
338
+
339
+ # Is this key name sensitive under the context's clean configuration?
340
+ sub key {
341
+ my ($ctx, $key) = @_;
342
+ return sensitive_key(config($ctx), $key);
343
+ }
344
+
6
345
  package ProjectNameUtilities;
7
346
 
8
347
  our %REGISTRY;
9
348
 
10
349
  $REGISTRY{clean} = sub {
11
350
  my ($ctx, $val) = @_;
12
- return $val;
351
+ return ProjectNameCleanSupport::clean($ctx, $val);
352
+ };
353
+
354
+ $REGISTRY{clean_add} = sub {
355
+ my ($ctx, $value) = @_;
356
+ return ProjectNameCleanSupport::add($ctx, $value);
13
357
  };
14
358
 
15
359
  1;
@@ -5,6 +5,7 @@ use warnings;
5
5
 
6
6
  use File::Basename ();
7
7
  use Cwd ();
8
+ use Scalar::Util ();
8
9
 
9
10
  my $__dir;
10
11
  BEGIN { $__dir = File::Basename::dirname(Cwd::abs_path(__FILE__)) }
@@ -17,12 +18,7 @@ our %REGISTRY;
17
18
 
18
19
  $REGISTRY{done} = sub {
19
20
  my ($ctx) = @_;
20
- my $ctrl = $ctx->{ctrl};
21
- if ($ctrl->{explain}) {
22
- $ctrl->{explain} = $ctx->{utility}{clean}->($ctx, $ctrl->{explain});
23
- my $er = $ctrl->{explain}{result};
24
- delete $er->{err} if Voxgig::Struct::ismap($er);
25
- }
21
+ $REGISTRY{clean_explain}->($ctx);
26
22
  if ($ctx->{result} && $ctx->{result}{ok}) {
27
23
  return $ctx->{result}{resdata};
28
24
  }
@@ -31,4 +27,26 @@ $REGISTRY{done} = sub {
31
27
  return $ctx->{utility}{make_error}->($ctx, undef);
32
28
  };
33
29
 
30
+ # The caller's own hash is the explain record (the control is built from it,
31
+ # and a stream copies only its ctrl), so the cleaned copy is written back
32
+ # INTO it: assigning a fresh hash would leave the caller holding the raw one.
33
+ $REGISTRY{clean_explain} = sub {
34
+ my ($ctx) = @_;
35
+ my $explain = $ctx->{ctrl}{explain};
36
+ return unless Voxgig::Struct::ismap($explain);
37
+ my $cleaned = $ctx->{utility}{clean}->($ctx, $explain);
38
+ if (Voxgig::Struct::ismap($cleaned)
39
+ && Scalar::Util::refaddr($cleaned) != Scalar::Util::refaddr($explain)) {
40
+ %$explain = %$cleaned;
41
+ }
42
+ # A copy: with clean off, explain.result is the live result make_error reads.
43
+ my $er = $explain->{result};
44
+ if (Voxgig::Struct::ismap($er)) {
45
+ my %pruned = %$er;
46
+ delete $pruned{err};
47
+ $explain->{result} = \%pruned;
48
+ }
49
+ return;
50
+ };
51
+
34
52
  1;
@@ -13,6 +13,7 @@ require(Cwd::abs_path("$__dir/../core/context.pm"));
13
13
  require(Cwd::abs_path("$__dir/../core/operation.pm"));
14
14
  require(Cwd::abs_path("$__dir/../core/result.pm"));
15
15
  require(Cwd::abs_path("$__dir/../core/error.pm"));
16
+ require(Cwd::abs_path("$__dir/clean.pm"));
16
17
 
17
18
  package ProjectNameUtilities;
18
19
 
@@ -33,11 +34,14 @@ $REGISTRY{make_error} = sub {
33
34
  $err = $result->{err} if !defined $err;
34
35
  $err = $ctx->make_error('unknown', 'unknown error') if !defined $err;
35
36
 
37
+ # A bare context (no client, no utility) still cleans, through the
38
+ # schema defaults.
39
+ my $clean = ($ctx->{utility} && $ctx->{utility}{clean}) || $REGISTRY{clean};
40
+
36
41
  my $errmsg = (Scalar::Util::blessed($err) && $err->isa('ProjectNameError'))
37
42
  ? $err->{msg} : "$err";
38
43
  $errmsg =~ s/\s+\z//;
39
- my $msg = "ProjectNameSDK: $opname: $errmsg";
40
- $msg = $ctx->{utility}{clean}->($ctx, $msg);
44
+ my $msg = $clean->($ctx, "ProjectNameSDK: $opname: $errmsg");
41
45
 
42
46
  $result->{err} = undef;
43
47
  my $spec = $ctx->{spec};
@@ -46,12 +50,21 @@ $REGISTRY{make_error} = sub {
46
50
  $ctx->{ctrl}{explain}{err} = { 'message' => $msg };
47
51
  }
48
52
 
53
+ # The context stays reachable for a debugger (`$err->ctx`) and is part of
54
+ # no dump of the error; result and spec are cleaned COPIES, so masking
55
+ # them never masks the pipeline's own objects.
49
56
  my $sdk_err = ProjectNameError->new('', $msg, $ctx);
50
- $sdk_err->{result} = $ctx->{utility}{clean}->($ctx, $result);
51
- $sdk_err->{spec} = $ctx->{utility}{clean}->($ctx, $spec);
57
+ $sdk_err->{result} = $clean->($ctx, $result);
58
+ $sdk_err->{spec} = $clean->($ctx, $spec);
52
59
  $sdk_err->{code} = $err->{code}
53
60
  if Scalar::Util::blessed($err) && $err->isa('ProjectNameError');
54
61
 
62
+ # Promote the HTTP status to the top level, so a consumer can branch on
63
+ # `$err->{status}` instead of reaching into `$err->{result}`.
64
+ $sdk_err->{status} = defined $result->{status} ? $result->{status} : -1;
65
+
66
+ $clean->($ctx, $sdk_err);
67
+
55
68
  $ctx->{ctrl}{err} = $sdk_err;
56
69
 
57
70
  # Fire PreUnexpected so observability features (metrics, telemetry, audit,
@@ -11,6 +11,7 @@ BEGIN { $__dir = File::Basename::dirname(Cwd::abs_path(__FILE__)) }
11
11
  require(Cwd::abs_path("$__dir/../lib/Voxgig/Struct.pm"));
12
12
  require(Cwd::abs_path("$__dir/../core/helpers.pm"));
13
13
  require(Cwd::abs_path("$__dir/../schema.pm"));
14
+ require(Cwd::abs_path("$__dir/clean.pm"));
14
15
 
15
16
  package ProjectNameUtilities;
16
17
 
@@ -89,6 +90,27 @@ $REGISTRY{make_options} = sub {
89
90
  $opts = {} unless Voxgig::Struct::ismap($opts);
90
91
  delete $opts->{extend};
91
92
 
93
+ my $config = $ctx->{config} || {};
94
+ my $cfgopts = Voxgig::Struct::ismap($config->{options}) ? $config->{options} : {};
95
+
96
+ # The secret registry exists BEFORE validation, fed from the raw input, so
97
+ # the constructor's own rejection of a mistyped credential is clean too.
98
+ my $cleancfg = ProjectNameCleanSupport::make_config(Voxgig::Struct::merge([
99
+ {},
100
+ grep { Voxgig::Struct::ismap($_) }
101
+ (Voxgig::Struct::clone(ProjectNameSchema::optspec()->{clean}),
102
+ Voxgig::Struct::clone($cfgopts->{clean}), $opts->{clean}),
103
+ ]));
104
+ my $cleanctx = { 'options' => { '__derived__' => { 'clean' => $cleancfg } } };
105
+ my %rawscan = %$opts;
106
+ delete $rawscan{clean};
107
+ ProjectNameCleanSupport::add_options($cleanctx, \%rawscan);
108
+ for my $block ($cfgopts, $opts) {
109
+ for my $raw (@{ ProjectNameCleanSupport::splitvalues(ProjectNameHelpers::gpath($block, 'clean.values')) }) {
110
+ ProjectNameCleanSupport::add($cleanctx, $raw);
111
+ }
112
+ }
113
+
92
114
  # Feature add-order. options.feature may be given as an ordered ARRAY of
93
115
  # { name, active, ...opts } entries (the array position IS the order in
94
116
  # which features are added), or as a { name => {opts} } map. Normalize an
@@ -111,9 +133,6 @@ $REGISTRY{make_options} = sub {
111
133
  $opts->{feature} = \%fmap;
112
134
  }
113
135
 
114
- my $config = $ctx->{config} || {};
115
- my $cfgopts = Voxgig::Struct::ismap($config->{options}) ? $config->{options} : {};
116
-
117
136
  # THE OPTION SPEC IS GENERATED, NOT WRITTEN HERE.
118
137
  #
119
138
  # Built from the model: `main.kit.optspec` for the standard options, plus one
@@ -146,7 +165,10 @@ $REGISTRY{make_options} = sub {
146
165
  # TARGETS, so without this one client's options (headers, server, ...) are
147
166
  # written into the shared config and inherited by every client after it.
148
167
  my $merged = Voxgig::Struct::merge([{}, Voxgig::Struct::clone($cfgopts), $opts]);
149
- my $validated = Voxgig::Struct::validate($merged, $optspec);
168
+ my $validated = eval { Voxgig::Struct::validate($merged, $optspec) };
169
+ if (my $verr = $@) {
170
+ die ProjectNameCleanSupport::clean($cleanctx, $verr);
171
+ }
150
172
  $opts = Voxgig::Struct::ismap($validated) ? $validated : {};
151
173
 
152
174
  # Restore the suppression the optspec default would otherwise erase.
@@ -162,15 +184,6 @@ $REGISTRY{make_options} = sub {
162
184
  $opts->{extend} = $extend_raw;
163
185
  }
164
186
 
165
- my $clean_keys = ProjectNameHelpers::gpath($opts, 'clean.keys');
166
- $clean_keys = 'key,token,id' unless defined $clean_keys && !ref $clean_keys;
167
- my @parts;
168
- for my $p (split /,/, $clean_keys) {
169
- $p =~ s/^\s+|\s+$//g;
170
- push @parts, Voxgig::Struct::escre($p) if '' ne $p;
171
- }
172
- my $keyre = join('|', @parts);
173
-
174
187
  # Resolve the feature add-order: an explicit array order (above) wins;
175
188
  # otherwise order the map test-first, then the remaining names sorted, so
176
189
  # the outcome is deterministic and `test` is always the base transport.
@@ -197,10 +210,16 @@ $REGISTRY{make_options} = sub {
197
210
  }
198
211
 
199
212
  $opts->{__derived__} = {
200
- 'clean' => ('' eq $keyre ? {} : { 'keyre' => $keyre }),
213
+ 'clean' => $cleancfg,
201
214
  'featureorder' => \@featureorder,
202
215
  };
203
216
 
217
+ # Again over the merged result: the config's own defaults can carry one.
218
+ # The extend instances are live objects, not option data.
219
+ my %scan = %$opts;
220
+ delete @scan{qw(__derived__ extend clean)};
221
+ ProjectNameCleanSupport::add_options($cleanctx, \%scan);
222
+
204
223
  return $opts;
205
224
  };
206
225
 
@@ -11,7 +11,7 @@ require_once __DIR__ . '/Response.php';
11
11
  require_once __DIR__ . '/Error.php';
12
12
  require_once __DIR__ . '/Helpers.php';
13
13
 
14
- class ProjectNameContext
14
+ class ProjectNameContext implements \JsonSerializable
15
15
  {
16
16
  public string $id;
17
17
  public array $out;
@@ -149,4 +149,27 @@ class ProjectNameContext
149
149
  {
150
150
  return new ProjectNameError($code, $msg, $this);
151
151
  }
152
+
153
+ // The serialised context leaves the pipeline (a logger, a dump), so it
154
+ // is cleaned; the live fields stay raw for the pipeline's own use.
155
+ public function jsonSerialize(): mixed
156
+ {
157
+ $record = [
158
+ 'id' => $this->id,
159
+ 'op' => $this->op,
160
+ 'spec' => $this->spec,
161
+ 'entity' => $this->entity,
162
+ 'result' => $this->result,
163
+ 'response' => $this->response,
164
+ 'meta' => $this->meta,
165
+ ];
166
+ $clean = null === $this->utility ? null : $this->utility->clean;
167
+ return is_callable($clean) ? $clean($this, $record) : $record;
168
+ }
169
+
170
+ public function __debugInfo(): array
171
+ {
172
+ $record = $this->jsonSerialize();
173
+ return is_array($record) ? $record : ['record' => $record];
174
+ }
152
175
  }
@@ -3,13 +3,12 @@ declare(strict_types=1);
3
3
 
4
4
  // ProjectName SDK error
5
5
 
6
- class ProjectNameError extends \Exception
6
+ class ProjectNameError extends \Exception implements \JsonSerializable
7
7
  {
8
8
  public bool $is_sdk_error;
9
9
  public string $sdk;
10
10
  public string $sdk_code;
11
11
  public string $msg;
12
- public mixed $ctx;
13
12
  public mixed $result;
14
13
  public mixed $spec;
15
14
 
@@ -24,6 +23,12 @@ class ProjectNameError extends \Exception
24
23
  // same field; php needs it spelled out because the class is typed.
25
24
  public int $status;
26
25
 
26
+ // The context stays reachable for a debugger (`ctx()`) and out of every
27
+ // serialiser: print_r and json_encode take the record below, and
28
+ // var_export renders a closure as empty where a property would dump the
29
+ // context's whole object graph, options and credential included.
30
+ private ?\Closure $ctxref;
31
+
27
32
  public function __construct(string $code = '', string $msg = '', mixed $ctx = null)
28
33
  {
29
34
  parent::__construct($msg);
@@ -31,12 +36,19 @@ class ProjectNameError extends \Exception
31
36
  $this->sdk = 'ProjectName';
32
37
  $this->sdk_code = $code;
33
38
  $this->msg = $msg;
34
- $this->ctx = $ctx;
39
+ $this->ctxref = null === $ctx ? null : static function () use ($ctx): mixed {
40
+ return $ctx;
41
+ };
35
42
  $this->result = null;
36
43
  $this->spec = null;
37
44
  $this->status = -1;
38
45
  }
39
46
 
47
+ public function ctx(): mixed
48
+ {
49
+ return null === $this->ctxref ? null : ($this->ctxref)();
50
+ }
51
+
40
52
  public function error(): string
41
53
  {
42
54
  return $this->msg;
@@ -46,4 +58,23 @@ class ProjectNameError extends \Exception
46
58
  {
47
59
  return $this->msg;
48
60
  }
61
+
62
+ // What make_error attached is already cleaned; the context is not part
63
+ // of the record.
64
+ public function jsonSerialize(): array
65
+ {
66
+ return [
67
+ 'sdk' => $this->sdk,
68
+ 'code' => $this->sdk_code,
69
+ 'message' => $this->getMessage(),
70
+ 'status' => $this->status,
71
+ 'result' => $this->result,
72
+ 'spec' => $this->spec,
73
+ ];
74
+ }
75
+
76
+ public function __debugInfo(): array
77
+ {
78
+ return $this->jsonSerialize();
79
+ }
49
80
  }
@@ -6,6 +6,8 @@ declare(strict_types=1);
6
6
  class ProjectNameUtility
7
7
  {
8
8
  public mixed $clean = null;
9
+ public mixed $clean_add = null;
10
+ public mixed $clean_explain = null;
9
11
  public mixed $done = null;
10
12
  public mixed $make_error = null;
11
13
  public mixed $feature_add = null;
@@ -57,6 +59,8 @@ class ProjectNameUtility
57
59
  {
58
60
  $u = new ProjectNameUtility();
59
61
  $u->clean = $src->clean;
62
+ $u->clean_add = $src->clean_add;
63
+ $u->clean_explain = $src->clean_explain;
60
64
  $u->done = $src->done;
61
65
  $u->make_error = $src->make_error;
62
66
  $u->feature_add = $src->feature_add;
@@ -86,7 +86,7 @@ class ProjectNameAuditFeature extends ProjectNameBaseFeature
86
86
  : ($this->options['actor'] ?? null);
87
87
  $actor = (is_string($actor) && $actor !== '') ? $actor : 'anonymous';
88
88
 
89
- $record = [
89
+ $record = ($ctx->utility->clean)($ctx, [
90
90
  'seq' => $this->seq,
91
91
  'ts' => $this->_now(),
92
92
  'actor' => $actor,
@@ -95,7 +95,7 @@ class ProjectNameAuditFeature extends ProjectNameBaseFeature
95
95
  'outcome' => $outcome,
96
96
  'status' => $ctx->result !== null ? $ctx->result->status : null,
97
97
  'correlationId' => $ctx->id,
98
- ];
98
+ ]);
99
99
 
100
100
  $client = $this->client;
101
101
  $client->_audit['records'][] = $record;