@voxgig/sdkgen 4.8.2 → 4.8.3

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 (376) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/action/doctor.d.ts +1 -0
  3. package/dist/action/doctor.js +50 -2
  4. package/dist/action/doctor.js.map +1 -1
  5. package/dist/helpers/naming.js +4 -2
  6. package/dist/helpers/naming.js.map +1 -1
  7. package/dist/tsconfig.tsbuildinfo +1 -1
  8. package/model/sdkgen.aon +21 -0
  9. package/package.json +1 -1
  10. package/project/.sdk/model/feature/secrets.aon +120 -18
  11. package/project/.sdk/model/target/c.aon +10 -0
  12. package/project/.sdk/model/target/clojure.aon +13 -0
  13. package/project/.sdk/model/target/cpp.aon +10 -0
  14. package/project/.sdk/model/target/csharp.aon +9 -0
  15. package/project/.sdk/model/target/dart.aon +10 -0
  16. package/project/.sdk/model/target/elixir.aon +9 -0
  17. package/project/.sdk/model/target/go.aon +13 -0
  18. package/project/.sdk/model/target/java.aon +9 -0
  19. package/project/.sdk/model/target/js.aon +7 -0
  20. package/project/.sdk/model/target/kotlin.aon +9 -0
  21. package/project/.sdk/model/target/lean.aon +17 -0
  22. package/project/.sdk/model/target/lua.aon +8 -0
  23. package/project/.sdk/model/target/ocaml.aon +9 -0
  24. package/project/.sdk/model/target/perl.aon +8 -0
  25. package/project/.sdk/model/target/php.aon +8 -0
  26. package/project/.sdk/model/target/py.aon +13 -0
  27. package/project/.sdk/model/target/rb.aon +8 -0
  28. package/project/.sdk/model/target/rust.aon +10 -0
  29. package/project/.sdk/model/target/scala.aon +21 -2
  30. package/project/.sdk/model/target/swift.aon +18 -0
  31. package/project/.sdk/model/target/ts.aon +13 -0
  32. package/project/.sdk/src/cmp/clojure/Package_clojure.ts +9 -2
  33. package/project/.sdk/src/cmp/cpp/Gitignore_cpp.ts +3 -0
  34. package/project/.sdk/src/cmp/dart/Test_dart.ts +2 -0
  35. package/project/.sdk/src/cmp/elixir/Package_elixir.ts +4 -1
  36. package/project/.sdk/src/cmp/go/Config_go.ts +59 -2
  37. package/project/.sdk/src/cmp/go/Main_go.ts +8 -2
  38. package/project/.sdk/src/cmp/java/Test_java.ts +6 -5
  39. package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +6 -5
  40. package/project/.sdk/src/cmp/lean/Package_lean.ts +23 -0
  41. package/project/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +1 -0
  42. package/project/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +1 -0
  43. package/project/.sdk/src/cmp/ocaml/Gitignore_ocaml.ts +1 -0
  44. package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +7 -3
  45. package/project/.sdk/src/cmp/py/Config_py.ts +82 -1
  46. package/project/.sdk/src/cmp/py/Main_py.ts +44 -0
  47. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +2 -0
  48. package/project/.sdk/src/cmp/swift/Main_swift.ts +10 -0
  49. package/project/.sdk/src/cmp/swift/Package_swift.ts +13 -1
  50. package/project/.sdk/src/cmp/ts/Config_ts.ts +42 -17
  51. package/project/.sdk/src/cmp/ts/fragment/Config.data.fragment.ts +13 -1
  52. package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +13 -1
  53. package/project/.sdk/tm/c/Makefile +38 -3
  54. package/project/.sdk/tm/c/tests/omni_resolver.h +361 -0
  55. package/project/.sdk/tm/c/tests/omni_smoke_test.c +237 -0
  56. package/project/.sdk/tm/c/tests/primary_corpus_test.c +205 -284
  57. package/project/.sdk/tm/c/tests/struct_corpus_test.c +292 -212
  58. package/project/.sdk/tm/c/tests/vendor/omni/json.c +811 -0
  59. package/project/.sdk/tm/c/tests/vendor/omni/omni.h +240 -0
  60. package/project/.sdk/tm/c/tests/vendor/omni/runner.c +940 -0
  61. package/project/.sdk/tm/c/tests/vendor/omni/util.c +351 -0
  62. package/project/.sdk/tm/c/utility/struct/utility.c +7 -2
  63. package/project/.sdk/tm/clojure/test/sdk/test/omni.clj +401 -0
  64. package/project/.sdk/tm/clojure/test/sdk/test/omni_smoke.clj +81 -0
  65. package/project/.sdk/tm/clojure/test/sdk/test/primary.clj +92 -58
  66. package/project/.sdk/tm/clojure/test/sdk/test/struct_corpus.clj +122 -149
  67. package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +8 -3
  68. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/json.clj +145 -0
  69. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/runner.clj +445 -0
  70. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/util.clj +145 -0
  71. package/project/.sdk/tm/cpp/Makefile +5 -1
  72. package/project/.sdk/tm/cpp/test/omni_resolver.hpp +473 -0
  73. package/project/.sdk/tm/cpp/test/omni_smoke_test.cpp +209 -0
  74. package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +243 -184
  75. package/project/.sdk/tm/cpp/test/runner_support.hpp +68 -181
  76. package/project/.sdk/tm/cpp/test/struct_corpus_test.cpp +183 -56
  77. package/project/.sdk/tm/cpp/test/vendor/omni/json.hpp +406 -0
  78. package/project/.sdk/tm/cpp/test/vendor/omni/omni.hpp +751 -0
  79. package/project/.sdk/tm/cpp/test/vendor/omni/util.hpp +256 -0
  80. package/project/.sdk/tm/cpp/utility/pipeline.hpp +7 -1
  81. package/project/.sdk/tm/csharp/test/OmniResolver.cs +491 -0
  82. package/project/.sdk/tm/csharp/test/OmniSmokeTest.cs +106 -0
  83. package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +299 -316
  84. package/project/.sdk/tm/csharp/test/Runner.cs +104 -269
  85. package/project/.sdk/tm/csharp/test/StructUtilityTest.cs +535 -724
  86. package/project/.sdk/tm/csharp/test/vendor/omni/Runner.cs +864 -0
  87. package/project/.sdk/tm/csharp/test/vendor/omni/Util.cs +347 -0
  88. package/project/.sdk/tm/csharp/utility/MakeSpec.cs +3 -1
  89. package/project/.sdk/tm/csharp/utility/PrepareMethod.cs +6 -1
  90. package/project/.sdk/tm/csharp/utility/struct/Struct.cs +21 -5
  91. package/project/.sdk/tm/dart/test/omni.dart +520 -0
  92. package/project/.sdk/tm/dart/test/omni_smoke_test.dart +143 -0
  93. package/project/.sdk/tm/dart/test/primary_test.dart +86 -28
  94. package/project/.sdk/tm/dart/test/struct_test.dart +438 -11
  95. package/project/.sdk/tm/dart/test/vendor/omni/omni.dart +7 -0
  96. package/project/.sdk/tm/dart/test/vendor/omni/runner.dart +653 -0
  97. package/project/.sdk/tm/dart/test/vendor/omni/util.dart +232 -0
  98. package/project/.sdk/tm/elixir/Makefile +11 -3
  99. package/project/.sdk/tm/elixir/test/omni_smoke_test.exs +117 -0
  100. package/project/.sdk/tm/elixir/test/primary_utility_test.exs +341 -16
  101. package/project/.sdk/tm/elixir/test/struct_corpus_test.exs +554 -9
  102. package/project/.sdk/tm/elixir/test/support/omni.ex +377 -0
  103. package/project/.sdk/tm/elixir/test/vendor/omni/json.ex +122 -0
  104. package/project/.sdk/tm/elixir/test/vendor/omni/runner.ex +623 -0
  105. package/project/.sdk/tm/elixir/test/vendor/omni/util.ex +187 -0
  106. package/project/.sdk/tm/go/core/context.go +32 -16
  107. package/project/.sdk/tm/go/feature/secrets/plugin/capability.go +261 -0
  108. package/project/.sdk/tm/go/feature/secrets/plugin/catalog.go +78 -0
  109. package/project/.sdk/tm/go/feature/secrets/plugin/config.go +652 -0
  110. package/project/.sdk/tm/go/feature/secrets/plugin/depend.go +250 -0
  111. package/project/.sdk/tm/go/feature/secrets/plugin/env.go +194 -0
  112. package/project/.sdk/tm/go/feature/secrets/plugin/export.go +80 -0
  113. package/project/.sdk/tm/go/feature/secrets/plugin/graph.go +238 -0
  114. package/project/.sdk/tm/go/feature/secrets/plugin/host.go +1575 -0
  115. package/project/.sdk/tm/go/feature/secrets/plugin/order.go +248 -0
  116. package/project/.sdk/tm/go/feature/secrets/plugin/point.go +184 -0
  117. package/project/.sdk/tm/go/feature/secrets/plugin/ref.go +123 -0
  118. package/project/.sdk/tm/go/feature/secrets/plugin/resolve.go +79 -0
  119. package/project/.sdk/tm/go/feature/secrets/plugin/types.go +296 -0
  120. package/project/.sdk/tm/go/feature/secrets/plugin/util.go +87 -0
  121. package/project/.sdk/tm/go/feature/secrets/plugin/version.go +161 -0
  122. package/project/.sdk/tm/go/feature/secrets/plugins/aws/aws.go +292 -0
  123. package/project/.sdk/tm/go/feature/secrets/plugins/aws/sigv4.go +201 -0
  124. package/project/.sdk/tm/go/feature/secrets/plugins/azuresecrets/azuresecrets.go +187 -0
  125. package/project/.sdk/tm/go/feature/secrets/plugins/boru/boru.go +184 -0
  126. package/project/.sdk/tm/go/feature/secrets/plugins/doppler/doppler.go +114 -0
  127. package/project/.sdk/tm/go/feature/secrets/plugins/gcpsecrets/gcpsecrets.go +156 -0
  128. package/project/.sdk/tm/go/feature/secrets/plugins/hashicorp/hashicorp.go +209 -0
  129. package/project/.sdk/tm/go/feature/secrets/plugins/httpjson/httpjson.go +241 -0
  130. package/project/.sdk/tm/go/feature/secrets/plugins/infisical/infisical.go +151 -0
  131. package/project/.sdk/tm/go/feature/secrets/plugins/onepassword/onepassword.go +152 -0
  132. package/project/.sdk/tm/go/feature/secrets/plugins/secretspec/secretspec.go +143 -0
  133. package/project/.sdk/tm/go/feature/secrets/sekreto/addr.go +120 -0
  134. package/project/.sdk/tm/go/feature/secrets/sekreto/providers.go +439 -0
  135. package/project/.sdk/tm/go/feature/secrets/sekreto/sekreto.go +685 -0
  136. package/project/.sdk/tm/go/feature/secrets_feature.go +675 -0
  137. package/project/.sdk/tm/go/src/feature/secrets/.gitkeep +0 -0
  138. package/project/.sdk/tm/go/test/feature/secrets/secrets_feature_test.go +799 -0
  139. package/project/.sdk/tm/go/test/omni/omni.go +897 -0
  140. package/project/.sdk/tm/go/test/omni/util.go +360 -0
  141. package/project/.sdk/tm/go/test/omniresolver_test.go +748 -0
  142. package/project/.sdk/tm/go/test/omnismoke_test.go +112 -0
  143. package/project/.sdk/tm/go/test/primary_utility_test.go +123 -191
  144. package/project/.sdk/tm/go/test/struct_utility_test.go +323 -16
  145. package/project/.sdk/tm/go/test/testsupport_test.go +294 -0
  146. package/project/.sdk/tm/go/utility/make_options.go +8 -1
  147. package/project/.sdk/tm/go/utility/prepare_method.go +5 -1
  148. package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +2 -2
  149. package/project/.sdk/tm/java/test/OmniResolver.java +355 -0
  150. package/project/.sdk/tm/java/test/OmniSmokeTest.java +99 -0
  151. package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +254 -280
  152. package/project/.sdk/tm/java/test/RunnerSupport.java +9 -194
  153. package/project/.sdk/tm/java/test/StructCorpusTest.java +119 -42
  154. package/project/.sdk/tm/java/test/vendor/omni/Json.java +287 -0
  155. package/project/.sdk/tm/java/test/vendor/omni/Runner.java +851 -0
  156. package/project/.sdk/tm/java/test/vendor/omni/Util.java +322 -0
  157. package/project/.sdk/tm/java/utility/MakeSpec.java +3 -1
  158. package/project/.sdk/tm/java/utility/PrepareMethod.java +5 -5
  159. package/project/.sdk/tm/java/utility/struct/Struct.java +17 -4
  160. package/project/.sdk/tm/js/src/utility/StructUtility.js +3 -3
  161. package/project/.sdk/tm/js/test/omni.js +251 -0
  162. package/project/.sdk/tm/js/test/omni.test.js +105 -0
  163. package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +6 -2
  164. package/project/.sdk/tm/js/test/utility/StructUtility.test.js +27 -2
  165. package/project/.sdk/tm/js/test/vendor/omni/index.js +77 -0
  166. package/project/.sdk/tm/js/test/vendor/omni/runner.js +613 -0
  167. package/project/.sdk/tm/js/test/vendor/omni/util.js +212 -0
  168. package/project/.sdk/tm/kotlin/core/Utility.kt +1 -1
  169. package/project/.sdk/tm/kotlin/test/OmniResolver.kt +343 -0
  170. package/project/.sdk/tm/kotlin/test/OmniSmokeTest.kt +100 -0
  171. package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +244 -262
  172. package/project/.sdk/tm/kotlin/test/RunnerSupport.kt +9 -178
  173. package/project/.sdk/tm/kotlin/test/StructCorpusTest.kt +121 -32
  174. package/project/.sdk/tm/kotlin/test/vendor/omni/Json.kt +264 -0
  175. package/project/.sdk/tm/kotlin/test/vendor/omni/Runner.kt +615 -0
  176. package/project/.sdk/tm/kotlin/test/vendor/omni/Util.kt +139 -0
  177. package/project/.sdk/tm/kotlin/utility/MakeSpecUrl.kt +6 -3
  178. package/project/.sdk/tm/kotlin/utility/Prepare.kt +6 -6
  179. package/project/.sdk/tm/kotlin/utility/struct/Struct.kt +18 -2
  180. package/project/.sdk/tm/lean/Makefile +12 -5
  181. package/project/.sdk/tm/lean/src/SdkUtility.lean +14 -1
  182. package/project/.sdk/tm/lean/test/OmniResolver.lean +358 -0
  183. package/project/.sdk/tm/lean/test/OmniSmoke.lean +174 -0
  184. package/project/.sdk/tm/lean/test/StructCorpus.lean +245 -574
  185. package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +155 -291
  186. package/project/.sdk/tm/lean/test/vendor/omni/Omni.lean +997 -0
  187. package/project/.sdk/tm/lua/test/omni.lua +456 -0
  188. package/project/.sdk/tm/lua/test/omni_smoke_test.lua +103 -0
  189. package/project/.sdk/tm/lua/test/primary_utility_test.lua +250 -509
  190. package/project/.sdk/tm/lua/test/struct_utility_test.lua +161 -70
  191. package/project/.sdk/tm/lua/test/vendor/omni/json.lua +268 -0
  192. package/project/.sdk/tm/lua/test/vendor/omni/regex.lua +385 -0
  193. package/project/.sdk/tm/lua/test/vendor/omni/runner.lua +641 -0
  194. package/project/.sdk/tm/lua/test/vendor/omni/util.lua +282 -0
  195. package/project/.sdk/tm/lua/utility/prepare_method.lua +5 -1
  196. package/project/.sdk/tm/lua/utility/struct/regex.lua +663 -0
  197. package/project/.sdk/tm/lua/utility/struct/struct.lua +660 -420
  198. package/project/.sdk/tm/ocaml/Makefile +37 -12
  199. package/project/.sdk/tm/ocaml/test/omni_resolver.ml +284 -0
  200. package/project/.sdk/tm/ocaml/test/omni_smoke_test.ml +169 -0
  201. package/project/.sdk/tm/ocaml/test/primary_utility_test.ml +84 -100
  202. package/project/.sdk/tm/ocaml/test/struct_corpus.ml +225 -201
  203. package/project/.sdk/tm/ocaml/test/vendor/omni/omni.ml +1157 -0
  204. package/project/.sdk/tm/perl/lib/Voxgig/Struct.pm +88 -12
  205. package/project/.sdk/tm/perl/t/omni.pm +647 -0
  206. package/project/.sdk/tm/perl/t/omni_smoke.t +87 -0
  207. package/project/.sdk/tm/perl/t/primary_utility.t +189 -487
  208. package/project/.sdk/tm/perl/t/struct_utility.t +455 -389
  209. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Runner.pm +649 -0
  210. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Util.pm +253 -0
  211. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni.pm +24 -0
  212. package/project/.sdk/tm/perl/utility/prepare_method.pm +7 -2
  213. package/project/.sdk/tm/php/test/Omni.php +691 -0
  214. package/project/.sdk/tm/php/test/OmniSmokeTest.php +93 -0
  215. package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +210 -571
  216. package/project/.sdk/tm/php/test/StructUtilityTest.php +320 -342
  217. package/project/.sdk/tm/php/test/vendor/omni/Runner.php +644 -0
  218. package/project/.sdk/tm/php/test/vendor/omni/Util.php +283 -0
  219. package/project/.sdk/tm/php/utility/MakeSpec.php +10 -3
  220. package/project/.sdk/tm/php/utility/PrepareBody.php +7 -1
  221. package/project/.sdk/tm/php/utility/PrepareMethod.php +6 -2
  222. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/__init__.py +36 -0
  223. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/capability.py +141 -0
  224. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/catalog.py +50 -0
  225. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/config.py +333 -0
  226. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/depend.py +198 -0
  227. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/env.py +147 -0
  228. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/export.py +52 -0
  229. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/graph.py +139 -0
  230. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/host.py +1053 -0
  231. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/order.py +171 -0
  232. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/point.py +95 -0
  233. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/ref.py +116 -0
  234. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/resolve.py +59 -0
  235. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/types.py +87 -0
  236. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/version.py +112 -0
  237. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/__init__.py +74 -0
  238. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/addr.py +116 -0
  239. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/aws.py +192 -0
  240. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/azuresecrets.py +120 -0
  241. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/boru.py +140 -0
  242. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/doppler.py +62 -0
  243. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/gcpsecrets.py +101 -0
  244. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/hashicorp.py +152 -0
  245. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/httpjson.py +115 -0
  246. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/infisical.py +92 -0
  247. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/onepassword.py +101 -0
  248. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/secretspec.py +119 -0
  249. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/sigv4.py +125 -0
  250. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/providers.py +211 -0
  251. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/sekreto.py +455 -0
  252. package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +467 -0
  253. package/project/.sdk/tm/py/pkg/utility/prepare_method.py +5 -1
  254. package/project/.sdk/tm/py/pkg/utility/voxgig_struct/__init__.py +0 -2
  255. package/project/.sdk/tm/py/pkg/utility/voxgig_struct/voxgig_struct.py +780 -529
  256. package/project/.sdk/tm/py/src/feature/secrets/.gitkeep +0 -0
  257. package/project/.sdk/tm/py/test/feature/__init__.py +0 -0
  258. package/project/.sdk/tm/py/test/feature/secrets/__init__.py +0 -0
  259. package/project/.sdk/tm/py/test/feature/secrets/test_secrets.py +337 -0
  260. package/project/.sdk/tm/py/test/omni.py +415 -0
  261. package/project/.sdk/tm/py/test/test_omni_smoke.py +74 -0
  262. package/project/.sdk/tm/py/test/test_primary_utility.py +144 -668
  263. package/project/.sdk/tm/py/test/test_struct_utility.py +74 -27
  264. package/project/.sdk/tm/py/test/voxgig_omni/__init__.py +62 -0
  265. package/project/.sdk/tm/py/test/voxgig_omni/runner.py +566 -0
  266. package/project/.sdk/tm/py/test/voxgig_omni/util.py +237 -0
  267. package/project/.sdk/tm/rb/test/omni.rb +505 -0
  268. package/project/.sdk/tm/rb/test/omni_smoke_test.rb +72 -0
  269. package/project/.sdk/tm/rb/test/primary_utility_test.rb +174 -560
  270. package/project/.sdk/tm/rb/test/struct_utility_test.rb +13 -7
  271. package/project/.sdk/tm/rb/test/vendor/omni/runner.rb +493 -0
  272. package/project/.sdk/tm/rb/test/vendor/omni/util.rb +199 -0
  273. package/project/.sdk/tm/rb/test/vendor/omni/voxgig_omni.rb +15 -0
  274. package/project/.sdk/tm/rb/utility/prepare_method.rb +5 -1
  275. package/project/.sdk/tm/rust/tests/common/mod.rs +19 -242
  276. package/project/.sdk/tm/rust/tests/omni_resolver/mod.rs +888 -0
  277. package/project/.sdk/tm/rust/tests/omni_smoke_test.rs +286 -0
  278. package/project/.sdk/tm/rust/tests/primary_utility_test.rs +318 -312
  279. package/project/.sdk/tm/rust/tests/struct_utility_test.rs +66 -28
  280. package/project/.sdk/tm/rust/tests/vendor/omni/json.rs +412 -0
  281. package/project/.sdk/tm/rust/tests/vendor/omni/mod.rs +38 -0
  282. package/project/.sdk/tm/rust/tests/vendor/omni/regex.rs +392 -0
  283. package/project/.sdk/tm/rust/tests/vendor/omni/runner.rs +1001 -0
  284. package/project/.sdk/tm/rust/tests/vendor/omni/util.rs +161 -0
  285. package/project/.sdk/tm/rust/utility/prepare_method.rs +5 -1
  286. package/project/.sdk/tm/scala/Makefile +16 -6
  287. package/project/.sdk/tm/scala/sdktest/OmniResolver.scala +497 -0
  288. package/project/.sdk/tm/scala/sdktest/OmniSmoke.scala +192 -0
  289. package/project/.sdk/tm/scala/sdktest/PrimaryCorpus.scala +47 -19
  290. package/project/.sdk/tm/scala/sdktest/StructCorpus.scala +0 -0
  291. package/project/.sdk/tm/scala/sdktest/vendor/omni/Json.scala +229 -0
  292. package/project/.sdk/tm/scala/sdktest/vendor/omni/Runner.scala +552 -0
  293. package/project/.sdk/tm/scala/sdktest/vendor/omni/Util.scala +104 -0
  294. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Constants.swift +10 -0
  295. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Inject.swift +28 -5
  296. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Injection.swift +5 -1
  297. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Minor.swift +4 -1
  298. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Validate.swift +15 -5
  299. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +6 -1
  300. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/OmniResolver.swift +474 -0
  301. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/OmniSmokeTest.swift +107 -0
  302. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +141 -178
  303. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/Runner.swift +17 -113
  304. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/StructUtilityTest.swift +295 -446
  305. package/project/.sdk/tm/swift/Tests/vendor/omni/Json.swift +364 -0
  306. package/project/.sdk/tm/swift/Tests/vendor/omni/Runner.swift +730 -0
  307. package/project/.sdk/tm/swift/Tests/vendor/omni/Util.swift +162 -0
  308. package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +7 -0
  309. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Capability.ts +148 -0
  310. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Catalog.ts +55 -0
  311. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Config.ts +344 -0
  312. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Depend.ts +205 -0
  313. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Env.ts +138 -0
  314. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Export.ts +46 -0
  315. package/project/.sdk/tm/ts/src/feature/secrets/plugin/FeatureHost.ts +349 -0
  316. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Graph.ts +181 -0
  317. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Host.ts +1132 -0
  318. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Order.ts +177 -0
  319. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Point.ts +119 -0
  320. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Ref.ts +102 -0
  321. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Resolve.ts +61 -0
  322. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Types.ts +112 -0
  323. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Version.ts +100 -0
  324. package/project/.sdk/tm/ts/src/feature/secrets/plugin/index.ts +37 -0
  325. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +163 -30
  326. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +27 -22
  327. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/aws.ts +26 -36
  328. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/azuresecrets.ts +19 -21
  329. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/boru.ts +36 -17
  330. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/doppler.ts +14 -21
  331. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/gcpsecrets.ts +27 -27
  332. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/hashicorp.ts +25 -39
  333. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/httpjson.ts +99 -0
  334. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/infisical.ts +14 -16
  335. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/onepassword.ts +15 -22
  336. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/secretspec.ts +98 -0
  337. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{Sigv4.ts → plugins/sigv4.ts} +7 -6
  338. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/addr.ts +97 -23
  339. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/builtin.ts +37 -0
  340. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/dotenv.ts +4 -17
  341. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/env.ts +4 -16
  342. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/file.ts +11 -25
  343. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/memory.ts +6 -23
  344. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/support.ts +106 -39
  345. package/project/.sdk/tm/ts/src/utility/StructUtility.ts +3 -3
  346. package/project/.sdk/tm/ts/test/omni.ts +104 -32
  347. package/project/.sdk/tm/ts/test/utility/StructUtility.test.ts +27 -0
  348. package/project/.sdk/tm/ts/test/vendor/omni/Runner.ts +32 -5
  349. package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +2 -2
  350. package/project/.sdk/tm/ts/test/vendor/omni/index.ts +2 -2
  351. package/project/.sdk/tm/zig/test/primary_utility_test.zig +1 -1
  352. package/project/.sdk/tm/zig/test/struct_runner.zig +5 -4
  353. package/project/sdkgen-package.json +1 -1
  354. package/src/action/doctor.ts +66 -2
  355. package/src/helpers/naming.ts +4 -2
  356. package/project/.sdk/tm/c/tests/runner.h +0 -274
  357. package/project/.sdk/tm/cpp/test/struct_runner.hpp +0 -314
  358. package/project/.sdk/tm/csharp/test/StructRunner.cs +0 -276
  359. package/project/.sdk/tm/dart/test/runner.dart +0 -406
  360. package/project/.sdk/tm/dart/test/struct_corpus.dart +0 -531
  361. package/project/.sdk/tm/elixir/test/support/struct_corpus.ex +0 -1088
  362. package/project/.sdk/tm/go/test/runner_test.go +0 -629
  363. package/project/.sdk/tm/go/test/struct_runner_test.go +0 -1094
  364. package/project/.sdk/tm/java/test/StructRunner.java +0 -281
  365. package/project/.sdk/tm/js/test/runner.js +0 -387
  366. package/project/.sdk/tm/kotlin/test/StructRunner.kt +0 -177
  367. package/project/.sdk/tm/lua/test/struct_runner.lua +0 -602
  368. package/project/.sdk/tm/ocaml/test/corpus_runner.ml +0 -185
  369. package/project/.sdk/tm/perl/t/struct_runner.pm +0 -275
  370. package/project/.sdk/tm/php/test/StructRunner.php +0 -275
  371. package/project/.sdk/tm/py/test/struct_runner.py +0 -411
  372. package/project/.sdk/tm/rb/test/struct_runner.rb +0 -309
  373. package/project/.sdk/tm/rust/tests/struct_runner/mod.rs +0 -424
  374. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/Registry.ts +0 -90
  375. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/http.ts +0 -66
  376. package/project/.sdk/tm/ts/test/vendor/omni/compat.ts +0 -188
@@ -0,0 +1,799 @@
1
+ // Behavioural tests for the secrets feature (vendored @voxgig/sekreto) -
2
+ // the go port of tm/ts/test/feature/secrets/Secrets.test.ts.
3
+ //
4
+ // The contract under test: the `apikey` OPTION keeps its exact old meaning
5
+ // and always wins, because SecretsFeature places it FIRST in the provider
6
+ // chain (a `memory` store named `options`) - explicit-beats-lookup falls
7
+ // out of sekreto's first-hit rule rather than from special-case logic.
8
+ // With the feature inactive nothing changes at all. With it active and the
9
+ // option unset, the chain (env, a custom provider, a vault) supplies the
10
+ // credential instead.
11
+ //
12
+ // This file lives in the test `feature/` container on purpose: `target
13
+ // add` trims it, along with the feature source and the vendored library,
14
+ // for a project whose model does not select `secrets`.
15
+ //
16
+ // The feature is CONSTRUCTED DIRECTLY and handed in through the
17
+ // `extend` option, so these tests hold in any generated tree - whether or
18
+ // not the project's model activated the feature (activation only changes
19
+ // whether config.go registers a constructor for it). The credential is
20
+ // asserted ON THE WIRE: a live-mode client with a recording system.fetch,
21
+ // driven through a real entity operation, which is what exercises the
22
+ // PreSpec resolution seam. (See the migration guide: an options-level
23
+ // assertion passes for a port that never consults the value.)
24
+
25
+ package secretstest
26
+
27
+ import (
28
+ "encoding/json"
29
+ "fmt"
30
+ "net/http"
31
+ "net/http/httptest"
32
+ "os"
33
+ "reflect"
34
+ "strings"
35
+ "sync"
36
+ "testing"
37
+ "time"
38
+ "unicode"
39
+
40
+ sdk "GOMODULE"
41
+ feat "GOMODULE/feature"
42
+ )
43
+
44
+ const envprefix = "PROJECTENV_TEST_SECRETS_"
45
+
46
+ // ---------------------------------------------------------------------
47
+ // The recording transport: system.fetch for a LIVE client, scripting one
48
+ // status per API call (the last repeating) and a token endpoint for the
49
+ // exchange tests.
50
+
51
+ type wirecall struct {
52
+ url string
53
+ auth string
54
+ has bool
55
+ body string
56
+ }
57
+
58
+ type wire struct {
59
+ mu sync.Mutex
60
+ calls []wirecall
61
+ apistatus []int
62
+ tokens []string
63
+ tokenpath string
64
+ respfield string
65
+ issued int
66
+ apicalls int
67
+ }
68
+
69
+ func makewire() *wire {
70
+ return &wire{
71
+ apistatus: []int{200},
72
+ tokens: []string{"ACCESS01", "ACCESS02", "ACCESS03"},
73
+ tokenpath: "auth/token",
74
+ respfield: "access_token",
75
+ }
76
+ }
77
+
78
+ func (w *wire) fetch(url string, fetchdef map[string]any) (map[string]any, error) {
79
+ w.mu.Lock()
80
+ defer w.mu.Unlock()
81
+
82
+ auth := ""
83
+ has := false
84
+ if headers, is := fetchdef["headers"].(map[string]any); is {
85
+ if v, found := headers["authorization"]; found {
86
+ auth, _ = v.(string)
87
+ has = true
88
+ }
89
+ }
90
+ body, _ := fetchdef["body"].(string)
91
+ w.calls = append(w.calls, wirecall{url: url, auth: auth, has: has, body: body})
92
+
93
+ if strings.HasSuffix(url, "/"+w.tokenpath) {
94
+ token := w.tokens[min(w.issued, len(w.tokens)-1)]
95
+ w.issued++
96
+ payload := map[string]any{w.respfield: token}
97
+ return map[string]any{
98
+ "status": 200, "statusText": "OK",
99
+ "headers": map[string]any{},
100
+ "json": (func() any)(func() any { return payload }),
101
+ }, nil
102
+ }
103
+
104
+ status := w.apistatus[min(w.apicalls, len(w.apistatus)-1)]
105
+ w.apicalls++
106
+ payload := map[string]any{"ok": status < 400}
107
+ return map[string]any{
108
+ "status": status, "statusText": "X",
109
+ "headers": map[string]any{},
110
+ "json": (func() any)(func() any { return payload }),
111
+ }, nil
112
+ }
113
+
114
+ func min(a, b int) int {
115
+ if a < b {
116
+ return a
117
+ }
118
+ return b
119
+ }
120
+
121
+ // api returns the recorded calls that did NOT go to the token endpoint.
122
+ func (w *wire) api() []wirecall {
123
+ w.mu.Lock()
124
+ defer w.mu.Unlock()
125
+ out := []wirecall{}
126
+ for _, c := range w.calls {
127
+ if !strings.HasSuffix(c.url, "/"+w.tokenpath) {
128
+ out = append(out, c)
129
+ }
130
+ }
131
+ return out
132
+ }
133
+
134
+ func (w *wire) token() []wirecall {
135
+ w.mu.Lock()
136
+ defer w.mu.Unlock()
137
+ out := []wirecall{}
138
+ for _, c := range w.calls {
139
+ if strings.HasSuffix(c.url, "/"+w.tokenpath) {
140
+ out = append(out, c)
141
+ }
142
+ }
143
+ return out
144
+ }
145
+
146
+ // ---------------------------------------------------------------------
147
+ // Support.
148
+
149
+ // The Authorization header carries the SPEC's credential prefix, which a
150
+ // TEMPLATE cannot know - so assert on the CREDENTIAL and let the prefix be
151
+ // whatever this SDK's API declares.
152
+ func credentialIs(t *testing.T, header string, token string) {
153
+ t.Helper()
154
+ if header != token && !strings.HasSuffix(header, " "+token) {
155
+ t.Fatalf("expected the authorization header to carry %s, got: %q", token, header)
156
+ }
157
+ }
158
+
159
+ // secretsClient builds a LIVE client carrying the secrets feature via the
160
+ // `extend` seam, wired to the recording transport.
161
+ func secretsClient(w *wire, sdkopts map[string]any) *sdk.ProjectNameSDK {
162
+ opts := map[string]any{
163
+ "base": "http://secrets.test/api",
164
+ "system": map[string]any{"fetch": w.fetch},
165
+ }
166
+ for k, v := range sdkopts {
167
+ opts[k] = v
168
+ }
169
+ return withSecrets(func(extend bool) *sdk.ProjectNameSDK {
170
+ if extend {
171
+ opts["extend"] = []any{feat.NewSecretsFeature()}
172
+ }
173
+ return sdk.NewProjectNameSDK(opts)
174
+ })
175
+ }
176
+
177
+ // withSecrets constructs the client and ADOPTS the feature via `extend`
178
+ // ONLY when the generated config did not already install it - when this
179
+ // SDK was generated with `secrets` model-active, the ordinary factory
180
+ // path builds the instance, and adding a second via extend would DOUBLE
181
+ // the feature: two transport wraps, two resolutions, and a token
182
+ // purchase the assertions cannot account for. (The py harness guards the
183
+ // same way via _has_feature.)
184
+ func withSecrets(build func(extend bool) *sdk.ProjectNameSDK) *sdk.ProjectNameSDK {
185
+ client := build(false)
186
+ if nil == secretsFeatureOf(client) {
187
+ client = build(true)
188
+ }
189
+ return client
190
+ }
191
+
192
+ func secretsOpts(extra map[string]any) map[string]any {
193
+ fopts := map[string]any{
194
+ "active": true,
195
+ "providers": []any{
196
+ map[string]any{"kind": "env", "prefix": envprefix},
197
+ },
198
+ }
199
+ for k, v := range extra {
200
+ fopts[k] = v
201
+ }
202
+ return map[string]any{"secrets": fopts}
203
+ }
204
+
205
+ // secretsFeatureOf digs the live feature back out of the client, for
206
+ // assertions against its Sekreto instance.
207
+ func secretsFeatureOf(client *sdk.ProjectNameSDK) *feat.SecretsFeature {
208
+ for _, f := range client.Features {
209
+ if sf, is := f.(*feat.SecretsFeature); is {
210
+ return sf
211
+ }
212
+ }
213
+ return nil
214
+ }
215
+
216
+ // driveEntityOpUntil performs real entity operations - which is what runs
217
+ // the PreSpec hook - until `stop` reports the observable state a test is
218
+ // waiting for. Each op's own outcome is irrelevant (no seeded data, a
219
+ // scripted response); an op the API does not define fails BEFORE the
220
+ // PreSpec hook, which is why several may need driving. Entity names come
221
+ // from the SDK's own config, because this file is a TEMPLATE and no
222
+ // project's entity names are known here.
223
+ func driveEntityOpUntil(t *testing.T, client *sdk.ProjectNameSDK, what string, stop func() bool) {
224
+ t.Helper()
225
+
226
+ entities, _ := client.OptionsMap()["entity"].(map[string]any)
227
+ clientval := reflect.ValueOf(client)
228
+
229
+ for name := range entities {
230
+ runes := []rune(name)
231
+ runes[0] = unicode.ToUpper(runes[0])
232
+ accessor := clientval.MethodByName(string(runes))
233
+ if !accessor.IsValid() || 1 != accessor.Type().NumIn() {
234
+ continue
235
+ }
236
+
237
+ ent := accessor.Call([]reflect.Value{
238
+ reflect.Zero(accessor.Type().In(0)),
239
+ })[0]
240
+
241
+ for _, opname := range []string{"List", "Load"} {
242
+ op := ent.MethodByName(opname)
243
+ if !op.IsValid() {
244
+ continue
245
+ }
246
+ in := make([]reflect.Value, op.Type().NumIn())
247
+ for i := range in {
248
+ in[i] = reflect.Zero(op.Type().In(i))
249
+ }
250
+ op.Call(in)
251
+
252
+ if stop() {
253
+ return
254
+ }
255
+ }
256
+ }
257
+
258
+ t.Fatalf("no entity operation %s - nothing to assert on", what)
259
+ }
260
+
261
+ // driveEntityOp drives ops until one request reached the recorder.
262
+ func driveEntityOp(t *testing.T, client *sdk.ProjectNameSDK, w *wire) {
263
+ t.Helper()
264
+ before := len(w.api())
265
+ driveEntityOpUntil(t, client, "reached the transport", func() bool {
266
+ return before < len(w.api())
267
+ })
268
+ }
269
+
270
+ // ---------------------------------------------------------------------
271
+ // The feature-inactive baseline: bit-identical behaviour.
272
+
273
+ func TestSecretsInactive(t *testing.T) {
274
+
275
+ t.Run("apikey option behaves exactly as before", func(t *testing.T) {
276
+ client := sdk.TestSDK(nil, map[string]any{"apikey": "OPTKEY01"})
277
+ fetchdef, err := client.Prepare(map[string]any{"path": "/"})
278
+ if err != nil {
279
+ t.Fatalf("prepare failed: %v", err)
280
+ }
281
+ headers, _ := fetchdef["headers"].(map[string]any)
282
+ auth, _ := headers["authorization"].(string)
283
+ credentialIs(t, auth, "OPTKEY01")
284
+
285
+ if nil != secretsFeatureOf(client) {
286
+ t.Fatal("no model activation, no extend: the feature must not be installed")
287
+ }
288
+ })
289
+
290
+ t.Run("no apikey means no authorization header", func(t *testing.T) {
291
+ client := sdk.TestSDK(nil, nil)
292
+ fetchdef, err := client.Prepare(map[string]any{"path": "/"})
293
+ if err != nil {
294
+ t.Fatalf("prepare failed: %v", err)
295
+ }
296
+ headers, _ := fetchdef["headers"].(map[string]any)
297
+ if _, has := headers["authorization"]; has {
298
+ t.Fatalf("unexpected authorization header: %v", headers["authorization"])
299
+ }
300
+ })
301
+ }
302
+
303
+ // ---------------------------------------------------------------------
304
+ // Active: the provider chain, driven through real entity operations.
305
+
306
+ func TestSecretsChain(t *testing.T) {
307
+
308
+ t.Run("apikey option still wins over the chain", func(t *testing.T) {
309
+ os.Setenv(envprefix+"APIKEY", "ENVKEY01")
310
+ defer os.Unsetenv(envprefix + "APIKEY")
311
+
312
+ w := makewire()
313
+ client := secretsClient(w, map[string]any{
314
+ "apikey": "OPTKEY01",
315
+ "feature": secretsOpts(nil),
316
+ })
317
+
318
+ driveEntityOp(t, client, w)
319
+ call := w.api()[0]
320
+ credentialIs(t, call.auth, "OPTKEY01")
321
+
322
+ // The explicit option is a real store, not a special case: a
323
+ // directed read names it like any other.
324
+ sf := secretsFeatureOf(client)
325
+ if nil == sf {
326
+ t.Fatal("the extend seam did not install the feature")
327
+ }
328
+ found, err := sf.Sekreto().GetFrom("options", "apikey")
329
+ if err != nil || "OPTKEY01" != found {
330
+ t.Fatalf("directed read of the options store: %q, %v", found, err)
331
+ }
332
+ })
333
+
334
+ t.Run("an omitted apikey defers to the chain at the transport seam", func(t *testing.T) {
335
+ os.Setenv(envprefix+"APIKEY", "ENVKEY02")
336
+ defer os.Unsetenv(envprefix + "APIKEY")
337
+
338
+ w := makewire()
339
+ client := secretsClient(w, map[string]any{"feature": secretsOpts(nil)})
340
+
341
+ // Before any op, nothing has been resolved.
342
+ if v, _ := client.OptionsMap()["apikey"].(string); "" != v {
343
+ t.Fatalf("apikey resolved before any operation: %q", v)
344
+ }
345
+
346
+ driveEntityOp(t, client, w)
347
+
348
+ // Resolution happens AT THE TRANSPORT - the one seam every wire
349
+ // path crosses - so the credential is on the wire, not merely
350
+ // resolved. go holds it in FEATURE STATE and injects there; the
351
+ // options map is never mutated (it stays raced-read-safe for
352
+ // every concurrent operation), so the state assertion reads the
353
+ // feature.
354
+ credentialIs(t, w.api()[0].auth, "ENVKEY02")
355
+ if v := secretsFeatureOf(client).Credential(); "ENVKEY02" != v {
356
+ t.Fatalf("the entity op did not resolve the secret through PreSpec: %q", v)
357
+ }
358
+ if v, _ := client.OptionsMap()["apikey"].(string); "" != v {
359
+ t.Fatalf("the options map must stay unwritten (frozen after construction), got apikey=%q", v)
360
+ }
361
+ })
362
+
363
+ t.Run("custom provider objects are accepted verbatim", func(t *testing.T) {
364
+ asked := []string{}
365
+ w := makewire()
366
+ client := secretsClient(w, map[string]any{
367
+ "feature": map[string]any{"secrets": map[string]any{
368
+ "active": true,
369
+ "providers": []any{
370
+ &customProvider{
371
+ lookup: func(name string) (string, bool, error) {
372
+ asked = append(asked, name)
373
+ return "CUSTOM01", true, nil
374
+ },
375
+ },
376
+ },
377
+ }},
378
+ })
379
+
380
+ driveEntityOp(t, client, w)
381
+ credentialIs(t, w.api()[0].auth, "CUSTOM01")
382
+ if 1 > len(asked) || "apikey" != asked[0] {
383
+ t.Fatalf("the custom provider was asked %v, want [apikey ...]", asked)
384
+ }
385
+ })
386
+
387
+ t.Run("a miss everywhere leaves the header off", func(t *testing.T) {
388
+ os.Unsetenv(envprefix + "APIKEY")
389
+
390
+ w := makewire()
391
+ client := secretsClient(w, map[string]any{"feature": secretsOpts(nil)})
392
+
393
+ driveEntityOp(t, client, w)
394
+ call := w.api()[0]
395
+ if call.has {
396
+ t.Fatalf("a chain MISS must fall through to an unauthenticated request, got header %q", call.auth)
397
+ }
398
+ })
399
+
400
+ t.Run("a provider ERROR fails the op and nothing reaches the wire", func(t *testing.T) {
401
+ asked := false
402
+ w := makewire()
403
+ client := secretsClient(w, map[string]any{
404
+ "feature": map[string]any{"secrets": map[string]any{
405
+ "active": true,
406
+ "providers": []any{
407
+ &customProvider{
408
+ lookup: func(name string) (string, bool, error) {
409
+ asked = true
410
+ return "", false, fmt.Errorf("vault unreachable")
411
+ },
412
+ },
413
+ },
414
+ }},
415
+ })
416
+
417
+ driveEntityOpUntil(t, client, "consulted the chain", func() bool {
418
+ return asked
419
+ })
420
+
421
+ if 0 != len(w.api()) {
422
+ t.Fatalf("a broken vault must never yield a request: %d calls went out", len(w.api()))
423
+ }
424
+ })
425
+
426
+ t.Run("a provider recovers after a transient failure", func(t *testing.T) {
427
+ calls := 0
428
+ w := makewire()
429
+ client := secretsClient(w, map[string]any{
430
+ "feature": map[string]any{"secrets": map[string]any{
431
+ "active": true,
432
+ "providers": []any{
433
+ &customProvider{
434
+ lookup: func(name string) (string, bool, error) {
435
+ calls++
436
+ if 1 == calls {
437
+ return "", false, fmt.Errorf("vault unreachable")
438
+ }
439
+ return "RECOVERED01", true, nil
440
+ },
441
+ },
442
+ },
443
+ }},
444
+ })
445
+
446
+ // First op fails closed; a failed resolution is never cached, so
447
+ // the second op asks the chain again and succeeds.
448
+ driveEntityOpUntil(t, client, "consulted the chain", func() bool {
449
+ return 0 < calls
450
+ })
451
+ if 0 != len(w.api()) {
452
+ t.Fatal("the first op must not reach the wire")
453
+ }
454
+
455
+ driveEntityOp(t, client, w)
456
+ credentialIs(t, w.api()[0].auth, "RECOVERED01")
457
+ })
458
+
459
+ t.Run("auth nil suppresses the credential, chain or no chain", func(t *testing.T) {
460
+ os.Setenv(envprefix+"APIKEY", "ENVKEY03")
461
+ defer os.Unsetenv(envprefix + "APIKEY")
462
+
463
+ w := makewire()
464
+ client := secretsClient(w, map[string]any{
465
+ "auth": nil,
466
+ "apikey": "OPTKEY01",
467
+ "feature": secretsOpts(nil),
468
+ })
469
+
470
+ driveEntityOp(t, client, w)
471
+
472
+ // Nothing on the wire, even though the chain would have resolved:
473
+ // go's vendored struct treats a stored null as "no value"
474
+ // (fail-OPEN class), and makeOptions captures suppliedness before
475
+ // validate and restores the null after - the guard this pins.
476
+ call := w.api()[0]
477
+ if call.has {
478
+ t.Fatalf("auth nil must suppress the credential, got header %q", call.auth)
479
+ }
480
+
481
+ // The suppression survives option validation rather than being
482
+ // replaced by the optspec's default auth map.
483
+ opts := client.OptionsMap()
484
+ authval, authgiven := opts["auth"]
485
+ if !authgiven || nil != authval {
486
+ t.Fatalf("options.auth must stay a present null, got (%v, present=%v)", authval, authgiven)
487
+ }
488
+ })
489
+ }
490
+
491
+ // customProvider is a sekreto.Provider built in code (the interface is
492
+ // structural: Lookup + Describe).
493
+ type customProvider struct {
494
+ lookup func(name string) (string, bool, error)
495
+ }
496
+
497
+ func (p *customProvider) Lookup(name string) (string, bool, error) {
498
+ return p.lookup(name)
499
+ }
500
+
501
+ func (p *customProvider) Describe() string { return "custom:test" }
502
+
503
+ // ---------------------------------------------------------------------
504
+ // The access-token exchange.
505
+
506
+ func TestSecretsExchange(t *testing.T) {
507
+
508
+ t.Run("the refresh token buys an access token, and a spent one is rebought once", func(t *testing.T) {
509
+ os.Setenv(envprefix+"REFRESH_TOKEN", "REFRESH01")
510
+ defer os.Unsetenv(envprefix + "REFRESH_TOKEN")
511
+
512
+ // First API call is refused, the retry succeeds.
513
+ w := makewire()
514
+ w.apistatus = []int{401, 200}
515
+
516
+ client := secretsClient(w, map[string]any{
517
+ "feature": secretsOpts(map[string]any{
518
+ "name": "refresh_token",
519
+ "exchange": map[string]any{"active": true},
520
+ }),
521
+ })
522
+
523
+ driveEntityOp(t, client, w)
524
+
525
+ if 2 != len(w.token()) {
526
+ t.Fatalf("expected the initial purchase plus one rebuy, got %d", len(w.token()))
527
+ }
528
+ if !strings.Contains(w.token()[0].body, "REFRESH01") {
529
+ t.Fatalf("the refresh token is sent in the request body, got %q", w.token()[0].body)
530
+ }
531
+
532
+ api := w.api()
533
+ if 2 != len(api) {
534
+ t.Fatalf("expected the request to be retried exactly once, got %d calls", len(api))
535
+ }
536
+ credentialIs(t, api[0].auth, "ACCESS01")
537
+ // The retry must carry the NEW token, not the spent one.
538
+ credentialIs(t, api[1].auth, "ACCESS02")
539
+ })
540
+
541
+ t.Run("test mode buys nothing and needs no token endpoint", func(t *testing.T) {
542
+ os.Setenv(envprefix+"REFRESH_TOKEN", "REFRESH01")
543
+ defer os.Unsetenv(envprefix + "REFRESH_TOKEN")
544
+
545
+ w := makewire()
546
+ client := withSecrets(func(extend bool) *sdk.ProjectNameSDK {
547
+ opts := map[string]any{
548
+ "system": map[string]any{"fetch": w.fetch},
549
+ "feature": secretsOpts(map[string]any{
550
+ "name": "refresh_token",
551
+ "exchange": map[string]any{"active": true},
552
+ }),
553
+ }
554
+ if extend {
555
+ opts["extend"] = []any{feat.NewSecretsFeature()}
556
+ }
557
+ return sdk.TestSDK(nil, opts)
558
+ })
559
+
560
+ driveEntityOpUntil(t, client, "resolved the fake token", func() bool {
561
+ return "" != secretsFeatureOf(client).Credential()
562
+ })
563
+
564
+ if 0 != len(w.calls) {
565
+ t.Fatalf("test mode must not do IO, saw %d calls", len(w.calls))
566
+ }
567
+ // A deterministic placeholder, so offline suites need no
568
+ // configuration.
569
+ if v := secretsFeatureOf(client).Credential(); "test-access_token" != v {
570
+ t.Fatalf("expected the fake test token, got %q", v)
571
+ }
572
+ })
573
+ }
574
+
575
+ // ---------------------------------------------------------------------
576
+ // Review-hardening pins (vendor-tag rollout, PR review): the exchange
577
+ // works with ORDINARY options (no custom transport), the token body is
578
+ // real JSON, an uncached miss retracts the credential, and a failed
579
+ // resolution recovers safely under concurrency.
580
+
581
+ // The exchange with NO system.fetch: the raw fallback transport carries
582
+ // the purchase, and the body is MARSHALLED - a refresh token full of
583
+ // JSON-hostile characters must arrive as that literal value. End to end
584
+ // over real HTTP (httptest), token purchase and API call alike.
585
+ func TestSecretsExchangeRawFetch(t *testing.T) {
586
+ tricky := "re\"fresh\\to\nken"
587
+
588
+ var mu sync.Mutex
589
+ gotrefresh := ""
590
+ gotauth := ""
591
+
592
+ srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
593
+ if strings.HasSuffix(req.URL.Path, "/auth/token") {
594
+ var body map[string]any
595
+ json.NewDecoder(req.Body).Decode(&body)
596
+ mu.Lock()
597
+ gotrefresh, _ = body["refresh_token"].(string)
598
+ mu.Unlock()
599
+ res.Header().Set("content-type", "application/json")
600
+ res.Write([]byte(`{"access_token": "RAWTOK01"}`))
601
+ return
602
+ }
603
+ mu.Lock()
604
+ gotauth = req.Header.Get("authorization")
605
+ mu.Unlock()
606
+ res.Header().Set("content-type", "application/json")
607
+ res.Write([]byte(`{}`))
608
+ }))
609
+ defer srv.Close()
610
+
611
+ // No system.fetch anywhere: the API call takes the SDK's default
612
+ // transport and the token purchase takes the feature's raw fallback.
613
+ client := withSecrets(func(extend bool) *sdk.ProjectNameSDK {
614
+ opts := map[string]any{
615
+ "base": srv.URL + "/api",
616
+ "feature": map[string]any{"secrets": map[string]any{
617
+ "active": true,
618
+ "name": "refresh_token",
619
+ "exchange": map[string]any{"active": true, "refresh": tricky},
620
+ }},
621
+ }
622
+ if extend {
623
+ opts["extend"] = []any{feat.NewSecretsFeature()}
624
+ }
625
+ return sdk.NewProjectNameSDK(opts)
626
+ })
627
+
628
+ driveEntityOpUntil(t, client, "reached the httptest server", func() bool {
629
+ mu.Lock()
630
+ defer mu.Unlock()
631
+ return "" != gotauth
632
+ })
633
+
634
+ mu.Lock()
635
+ defer mu.Unlock()
636
+ if tricky != gotrefresh {
637
+ t.Fatalf("the refresh token must arrive as its literal value "+
638
+ "(marshalled, not concatenated): want %q got %q", tricky, gotrefresh)
639
+ }
640
+ credentialIs(t, gotauth, "RAWTOK01")
641
+ }
642
+
643
+ // With `cache: false`, a provider that answered once and then reports a
644
+ // MISS (a revoked secret) must RETRACT the credential the feature wrote -
645
+ // prepareAuth must stop transmitting it.
646
+ func TestSecretsUncachedMissRetracts(t *testing.T) {
647
+ var mu sync.Mutex
648
+ have := true
649
+
650
+ w := makewire()
651
+ client := secretsClient(w, map[string]any{
652
+ "feature": map[string]any{"secrets": map[string]any{
653
+ "active": true,
654
+ "cache": false,
655
+ "providers": []any{
656
+ &customProvider{
657
+ lookup: func(name string) (string, bool, error) {
658
+ mu.Lock()
659
+ defer mu.Unlock()
660
+ if have {
661
+ return "REVOCABLE01", true, nil
662
+ }
663
+ return "", false, nil
664
+ },
665
+ },
666
+ },
667
+ }},
668
+ })
669
+
670
+ driveEntityOp(t, client, w)
671
+ credentialIs(t, w.api()[0].auth, "REVOCABLE01")
672
+
673
+ mu.Lock()
674
+ have = false
675
+ mu.Unlock()
676
+
677
+ driveEntityOp(t, client, w)
678
+ last := w.api()[len(w.api())-1]
679
+ if last.has && "" != last.auth {
680
+ t.Fatalf("after the chain reports a miss, the retracted credential "+
681
+ "must not go out; the wire saw %q", last.auth)
682
+ }
683
+ }
684
+
685
+ // The RAW paths - Direct and Graphql - run no feature hooks at all, so
686
+ // for them the transport seam is the ONLY place resolution can happen.
687
+ // This is the pin that Direct gets the chain credential (and the same
688
+ // fail-closed refusal) without any entity pipeline involved.
689
+ func TestSecretsDirectPath(t *testing.T) {
690
+ os.Setenv(envprefix+"APIKEY", "DIRECTKEY01")
691
+ defer os.Unsetenv(envprefix + "APIKEY")
692
+
693
+ w := makewire()
694
+ client := secretsClient(w, map[string]any{
695
+ "allow": map[string]any{"op": "direct"},
696
+ "feature": secretsOpts(nil),
697
+ })
698
+
699
+ res, err := client.Direct(map[string]any{"path": "/direct-probe"})
700
+ if nil != err {
701
+ t.Fatalf("direct failed: %v", err)
702
+ }
703
+ if ok, _ := res["ok"].(bool); !ok {
704
+ t.Fatalf("direct refused: %v", res["err"])
705
+ }
706
+ if 1 != len(w.api()) {
707
+ t.Fatalf("expected one direct call on the wire, got %d", len(w.api()))
708
+ }
709
+ credentialIs(t, w.api()[0].auth, "DIRECTKEY01")
710
+
711
+ // And fail-closed holds for raw access too: a broken chain refuses
712
+ // the Direct call before anything reaches the wire.
713
+ broken := secretsClient(makewire(), map[string]any{
714
+ "allow": map[string]any{"op": "direct"},
715
+ "feature": map[string]any{"secrets": map[string]any{
716
+ "active": true,
717
+ "providers": []any{
718
+ &customProvider{
719
+ lookup: func(name string) (string, bool, error) {
720
+ return "", false, fmt.Errorf("vault unreachable")
721
+ },
722
+ },
723
+ },
724
+ }},
725
+ })
726
+ res, err = broken.Direct(map[string]any{"path": "/direct-probe"})
727
+ if nil != err {
728
+ t.Fatalf("direct must report the refusal in-band: %v", err)
729
+ }
730
+ if ok, _ := res["ok"].(bool); ok {
731
+ t.Fatal("a broken chain must refuse the raw path fail-closed")
732
+ }
733
+ }
734
+
735
+ // A provider failure closes the transport gate; a later retry that
736
+ // SUCCEEDS reopens it and every waiting operation goes out with the FRESH
737
+ // credential - never the stale pre-failure header, and never nothing.
738
+ func TestSecretsGateRecovery(t *testing.T) {
739
+ var mu sync.Mutex
740
+ mode := "fail"
741
+ release := make(chan struct{})
742
+
743
+ w := makewire()
744
+ client := secretsClient(w, map[string]any{
745
+ "feature": map[string]any{"secrets": map[string]any{
746
+ "active": true,
747
+ "cache": false,
748
+ "providers": []any{
749
+ &customProvider{
750
+ lookup: func(name string) (string, bool, error) {
751
+ mu.Lock()
752
+ m := mode
753
+ mu.Unlock()
754
+ if "fail" == m {
755
+ return "", false, fmt.Errorf("vault unreachable")
756
+ }
757
+ if "slow" == m {
758
+ <-release
759
+ }
760
+ return "FRESH01", true, nil
761
+ },
762
+ },
763
+ },
764
+ }},
765
+ })
766
+
767
+ // 1. The failure closes the gate: nothing reaches the wire.
768
+ driveEntityOpUntil(t, client, "was refused by the gate", func() bool { return true })
769
+ if 0 != len(w.api()) {
770
+ t.Fatalf("a failed resolution must keep the wire silent, saw %d calls", len(w.api()))
771
+ }
772
+
773
+ // 2. Recovery under concurrency: two operations race the slow retry;
774
+ // both must come out carrying the fresh credential.
775
+ mu.Lock()
776
+ mode = "slow"
777
+ mu.Unlock()
778
+
779
+ var wg sync.WaitGroup
780
+ for i := 0; i < 2; i++ {
781
+ wg.Add(1)
782
+ go func() {
783
+ defer wg.Done()
784
+ driveEntityOpUntil(t, client, "recovered", func() bool { return true })
785
+ }()
786
+ }
787
+ go func() {
788
+ time.Sleep(20 * time.Millisecond)
789
+ close(release)
790
+ }()
791
+ wg.Wait()
792
+
793
+ for _, call := range w.api() {
794
+ credentialIs(t, call.auth, "FRESH01")
795
+ }
796
+ if 0 == len(w.api()) {
797
+ t.Fatal("recovery must let the operations out")
798
+ }
799
+ }