@voxgig/sdkgen 4.8.1 → 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 +2 -2
  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,675 @@
1
+ package feature
2
+
3
+ import (
4
+ "encoding/json"
5
+ "io"
6
+ "net/http"
7
+ "strconv"
8
+ "strings"
9
+ "sync"
10
+ "time"
11
+
12
+ "GOMODULE/core"
13
+ plugin "GOMODULE/feature/secrets/plugin"
14
+ sekreto "GOMODULE/feature/secrets/sekreto"
15
+ )
16
+
17
+ // Secret access via a vendored @voxgig/sekreto provider chain, and the
18
+ // access-token exchange some APIs require on top of it. The go port of
19
+ // tm/ts/src/feature/secrets/SecretsFeature.ts - same contract, go idiom.
20
+ //
21
+ // The SDK's `apikey` option keeps exactly its old meaning: an explicit
22
+ // credential given in code. This feature makes it ONE SOURCE among several
23
+ // rather than the only one: when active, the apikey is resolved through a
24
+ // sekreto chain in which the explicit option (when set) is the FIRST
25
+ // provider - a `memory` store named `options` - so an explicit value always
26
+ // wins, by sekreto's own first-hit rule rather than by special-case logic.
27
+ //
28
+ // Resolution is effectively ASYNC (providers do IO), and the auth header is
29
+ // built by the synchronous prepareAuth inside makeSpec. The bridge is the
30
+ // feature hook pipeline: every entity op runs featureHook("PreSpec") before
31
+ // makeSpec, so the PreSpec hook below resolves the secret once and writes
32
+ // it into the LIVE options map where prepareAuth already looks (ctx.Options
33
+ // on the root context IS the options map the client clones for OptionsMap).
34
+ // Concurrent operations share the single in-flight resolution.
35
+ //
36
+ // MISS vs ERROR (sekreto's invariant): a provider MISS falls through - the
37
+ // op proceeds, unauthenticated if nothing else supplies a credential. A
38
+ // provider ERROR (unreachable vault, bad creds) must FAIL the op: a broken
39
+ // vault never degrades into an unauthenticated request. go's feature hooks
40
+ // are synchronous and cannot fail an operation from PreSpec the way ts's
41
+ // awaited hook rejection can - so, unlike ts, the transport is wrapped
42
+ // WHENEVER the feature is active, and the wrapper refuses to send while
43
+ // the last resolution stands failed. Fail-closed at the one seam every
44
+ // request must pass.
45
+ //
46
+ // EXCHANGE: some APIs will not take a long-lived credential at all. What
47
+ // the chain resolves is then a REFRESH token, which buys a short-lived
48
+ // ACCESS token from a token endpoint (`exchange.path`, relative to
49
+ // options.base); the access token is what every request carries, and when
50
+ // a response status in `exchange.statuses` (401) says it is spent the
51
+ // wrapper buys another and retries the same request once. Concurrent
52
+ // purchases share the one in-flight exchange; test mode buys nothing and
53
+ // answers with a deterministic fake token.
54
+ type SecretsFeature struct {
55
+ BaseFeature
56
+ client *core.ProjectNameSDK
57
+ options map[string]any
58
+
59
+ // The LIVE options map (root ctx options), where the resolved value
60
+ // lands so the sync prepareAuth sees it.
61
+ liveopts map[string]any
62
+
63
+ secretname string
64
+ cache bool
65
+ sek *sekreto.Sekreto
66
+
67
+ // Exchange state: nil config when off; the refresh credential the
68
+ // chain resolved; the single in-flight purchase.
69
+ exchange *secretsExchange
70
+ refresh string
71
+
72
+ mu sync.Mutex
73
+ resolving *secretsCall
74
+ buying *secretsBuy
75
+ initerr error
76
+
77
+ // The RESOLVED credential, held in feature state and injected into
78
+ // each request at the transport seam - NEVER written into the shared
79
+ // live options map. This is go's structural deviation from the ts
80
+ // reference (which writes options.apikey): the go request path reads
81
+ // ctx.Options raw on every operation goroutine, so a feature that
82
+ // mutated that map would race every concurrent operation. With the
83
+ // feature as sole holder, the options map is frozen after
84
+ // construction and every raw read is safe; the header the wire sees
85
+ // is identical, because the transport wrapper rewrites it from this
86
+ // value the same way prepareAuth builds it.
87
+ cred string
88
+ }
89
+
90
+ type secretsExchange struct {
91
+ path string
92
+ method string
93
+ request string
94
+ response string
95
+ statuses []int
96
+ retries int
97
+ }
98
+
99
+ // One shared in-flight resolution: late arrivals wait on done and read err.
100
+ type secretsCall struct {
101
+ done chan struct{}
102
+ err error
103
+ }
104
+
105
+ type secretsBuy struct {
106
+ done chan struct{}
107
+ token string
108
+ err error
109
+ }
110
+
111
+ func NewSecretsFeature() *SecretsFeature {
112
+ return &SecretsFeature{
113
+ BaseFeature: BaseFeature{
114
+ Version: "0.1.0",
115
+ Name: "secrets",
116
+ Active: true,
117
+ },
118
+ }
119
+ }
120
+
121
+ // Sekreto is the LIVE instance, for callers who want arbitrary secrets or
122
+ // redaction (the go spelling of ts's public sekreto() accessor). Never a
123
+ // clone: sekreto holds provider state that has to stay live to be worth
124
+ // anything.
125
+ func (f *SecretsFeature) Sekreto() *sekreto.Sekreto {
126
+ return f.sek
127
+ }
128
+
129
+ // Init is sync by feature contract: build the chain, never look anything
130
+ // up here.
131
+ func (f *SecretsFeature) Init(ctx *core.Context, options map[string]any) {
132
+ f.client = ctx.Client
133
+ f.options = options
134
+ f.liveopts = ctx.Options
135
+ f.Active = foptBool(options, "active", false)
136
+
137
+ if !f.Active {
138
+ return
139
+ }
140
+
141
+ f.secretname = foptStr(options, "name", "apikey")
142
+ if "" == f.secretname {
143
+ f.secretname = "apikey"
144
+ }
145
+ f.cache = foptBool(options, "cache", true)
146
+
147
+ // Exchange config, normalised once. Nil when off, so every later
148
+ // decision is a nil check.
149
+ xopts := foptMap(options, "exchange")
150
+ if foptBool(xopts, "active", false) {
151
+ statuses := []int{}
152
+ for _, s := range foptList(xopts, "statuses") {
153
+ statuses = append(statuses, core.ToInt(s))
154
+ }
155
+ if 0 == len(statuses) {
156
+ statuses = []int{401}
157
+ }
158
+ f.exchange = &secretsExchange{
159
+ path: foptStr(xopts, "path", "auth/token"),
160
+ method: foptStr(xopts, "method", "POST"),
161
+ request: foptStr(xopts, "request", "refresh_token"),
162
+ response: foptStr(xopts, "response", "access_token"),
163
+ statuses: statuses,
164
+ retries: foptInt(xopts, "retries", 1),
165
+ }
166
+ }
167
+
168
+ // The explicit credential, when set, is the first store in the chain.
169
+ //
170
+ // WHICH option that is depends on the exchange. Without one, the
171
+ // secret being resolved IS the credential the transport sends, so
172
+ // `apikey` is it. With one, the secret is a REFRESH token and `apikey`
173
+ // means the opposite thing - an access token the caller already holds
174
+ // - so the explicit seat belongs to `exchange.refresh`, and apikey is
175
+ // left alone to serve as the starting access token (see resolveonce).
176
+ explicit := ""
177
+ if nil == f.exchange {
178
+ explicit, _ = f.liveopts["apikey"].(string)
179
+ } else {
180
+ explicit = foptStr(xopts, "refresh", "")
181
+ }
182
+
183
+ specs := []*sekreto.ProviderSpec{}
184
+
185
+ if "" != explicit {
186
+ key, err := sekreto.EnvKey(f.secretname, "")
187
+ if nil == err {
188
+ specs = append(specs, &sekreto.ProviderSpec{
189
+ Kind: "memory",
190
+ Name: "options",
191
+ Values: map[string]string{key: explicit},
192
+ })
193
+ }
194
+ }
195
+
196
+ for _, p := range foptList(options, "providers") {
197
+ switch v := p.(type) {
198
+ case *sekreto.ProviderSpec:
199
+ specs = append(specs, v)
200
+ case sekreto.Provider:
201
+ // A provider already built joins the chain as it is.
202
+ specs = append(specs, &sekreto.ProviderSpec{Provider: v})
203
+ case map[string]any:
204
+ spec, err := sekreto.SpecOf(v)
205
+ if nil != err {
206
+ f.initerr = err
207
+ continue
208
+ }
209
+ specs = append(specs, spec)
210
+ }
211
+ }
212
+
213
+ // The plugin DEFINITIONS the model selected for this feature, emitted
214
+ // by Config generically from the catalogue's active `plugin.def`
215
+ // entries. Upstream sekreto's contract since the registry was retired:
216
+ // a kind not passed in Plugins is unknown to this Sekreto, so the
217
+ // model's choice of plugin groups IS the SDK's provider vocabulary.
218
+ plugs := []plugin.Definition{}
219
+ for _, d := range core.FeaturePlugins(f.Name) {
220
+ if def, is := d.(plugin.Definition); is {
221
+ plugs = append(plugs, def)
222
+ }
223
+ }
224
+
225
+ sek, err := sekreto.New(&sekreto.Options{
226
+ Providers: specs,
227
+ Plugins: plugs,
228
+ NoCache: !f.cache,
229
+ })
230
+ if nil != err {
231
+ // Init cannot fail the construction the way ts's throwing init
232
+ // does; the transport gate below refuses to send instead, which
233
+ // keeps a misconfigured chain fail-closed rather than silently
234
+ // unauthenticated.
235
+ f.initerr = err
236
+ return
237
+ }
238
+ f.sek = sek
239
+
240
+ // Wrap the transport: the fail-closed gate needs the seam whenever the
241
+ // feature is active, and the exchange (when on) additionally needs to
242
+ // SEE responses - expiry is only ever discovered from one, and this is
243
+ // the one place a response can be seen and the request tried again.
244
+ self := f
245
+ inner := ctx.Utility.Fetcher
246
+ ctx.Utility.Fetcher = func(ctx2 *core.Context, url string, fetchdef map[string]any) (any, error) {
247
+ return self.transport(ctx2, url, fetchdef, inner)
248
+ }
249
+ }
250
+
251
+ // resolve runs one resolution, shared by every concurrent caller. A
252
+ // settled SUCCESS is kept only when caching is on (`cache: false` means
253
+ // every resolve asks the chain again); a FAILURE is always cleared, so a
254
+ // transient vault outage never poisons the client permanently - the next
255
+ // operation asks the chain again.
256
+ func (f *SecretsFeature) resolve() error {
257
+ if nil != f.initerr {
258
+ return f.initerr
259
+ }
260
+
261
+ f.mu.Lock()
262
+ if call := f.resolving; nil != call {
263
+ f.mu.Unlock()
264
+ <-call.done
265
+ return call.err
266
+ }
267
+ call := &secretsCall{done: make(chan struct{})}
268
+ f.resolving = call
269
+ f.mu.Unlock()
270
+
271
+ err := f.resolveonce()
272
+
273
+ f.mu.Lock()
274
+ call.err = err
275
+ if nil != err || !f.cache {
276
+ f.resolving = nil
277
+ }
278
+ f.mu.Unlock()
279
+ close(call.done)
280
+
281
+ return err
282
+ }
283
+
284
+ func (f *SecretsFeature) resolveonce() error {
285
+ if nil == f.sek {
286
+ return nil
287
+ }
288
+
289
+ found, has, err := f.sek.Try(f.secretname)
290
+ if nil != err {
291
+ // A provider ERROR fails the op (via the transport gate); only a
292
+ // MISS falls through.
293
+ return err
294
+ }
295
+
296
+ if nil == f.exchange {
297
+ f.mu.Lock()
298
+ if has {
299
+ f.cred = found
300
+ } else {
301
+ // An UNCACHED miss after an earlier hit is a revocation: the
302
+ // chain now says no provider has the secret, so the resolved
303
+ // value must not keep going out on the wire. (An explicit
304
+ // apikey OPTION is never lost here - it seats FIRST in the
305
+ // chain as a memory provider, so the chain HITS while one is
306
+ // set and the miss branch is unreachable.)
307
+ f.cred = ""
308
+ }
309
+ f.mu.Unlock()
310
+ return nil
311
+ }
312
+
313
+ // Exchanging: what the chain resolved is the REFRESH token, kept for
314
+ // every later purchase. A miss is not fatal here - an explicit
315
+ // `apikey` may already hold a usable access token, and the API is
316
+ // what gets to say whether it does.
317
+ f.refresh = ""
318
+ if has {
319
+ f.refresh = found
320
+ }
321
+
322
+ f.mu.Lock()
323
+ apikey := f.cred
324
+ f.mu.Unlock()
325
+ if "" == apikey {
326
+ // A starting access token supplied as the OPTION: read from the
327
+ // frozen options map (no feature ever writes it).
328
+ apikey, _ = f.liveopts["apikey"].(string)
329
+ f.mu.Lock()
330
+ f.cred = apikey
331
+ f.mu.Unlock()
332
+ }
333
+ if "" != apikey {
334
+ // A starting access token was supplied. Spend it: if it is stale
335
+ // the API answers with an expiry status and the transport wrapper
336
+ // buys another, which is the same path expiry takes anyway.
337
+ return nil
338
+ }
339
+
340
+ _, err = f.buy()
341
+ return err
342
+ }
343
+
344
+ // transport wraps whatever transport was current at Init.
345
+ func (f *SecretsFeature) transport(ctx *core.Context, url string,
346
+ fetchdef map[string]any, inner core.FetcherFunc) (any, error) {
347
+
348
+ // Fail-closed, at the ONE seam every wire path crosses. Entity ops,
349
+ // Direct, Graphql and the exchange retries all come through this
350
+ // wrapper, so resolving HERE is what gives the raw paths - which run
351
+ // no feature hooks at all - the same credential the entity pipeline
352
+ // gets (ts resolves in its awaited PreSpec instead; go's header is
353
+ // rewritten below AFTER Prepare built it, so the transport is exactly
354
+ // early enough). resolve() is shared and cached: concurrent callers
355
+ // join the in-flight attempt, a cached success is free, and with
356
+ // `cache: false` the chain is asked once per REQUEST, which is that
357
+ // option's meaning. A provider ERROR refuses the request with the
358
+ // provider's error - never an unauthenticated send.
359
+ if nil != f.initerr {
360
+ return nil, f.initerr
361
+ }
362
+ if err := f.resolve(); nil != err {
363
+ return nil, err
364
+ }
365
+
366
+ // Inject the resolved credential into THIS request's header. The
367
+ // header was built by prepareAuth from the options apikey; the
368
+ // chain-resolved value lives in feature state instead (see `cred`),
369
+ // so the wrapper writes it here - same construction, same
370
+ // suppression rules - and the shared options map stays untouched.
371
+ if token := f.getcred(); "" != token {
372
+ f.reauth(fetchdef, token)
373
+ }
374
+
375
+ if nil == f.exchange {
376
+ return inner(ctx, url, fetchdef)
377
+ }
378
+
379
+ return f.withrefresh(ctx, url, fetchdef, inner)
380
+ }
381
+
382
+ // withrefresh buys a token and tries the request again when the API says
383
+ // the current one is spent.
384
+ //
385
+ // The retry rewrites the authorization header IN PLACE on the fetchdef,
386
+ // because the header was built by the synchronous prepareAuth before this
387
+ // request left, and it carries the token that just failed. Rebuilt the way
388
+ // prepareAuth builds it, from the same options auth.prefix, so the two
389
+ // cannot drift.
390
+ func (f *SecretsFeature) withrefresh(ctx *core.Context, url string,
391
+ fetchdef map[string]any, inner core.FetcherFunc) (any, error) {
392
+
393
+ // `auth: nil` is the documented way to send NO credential, and
394
+ // prepareAuth honours it by removing the header. A refusal of a
395
+ // deliberately unauthenticated request is not an expired token and
396
+ // cannot be fixed by buying one - retrying would transmit exactly the
397
+ // credential the caller suppressed.
398
+ if nil == f.liveopts["auth"] {
399
+ return inner(ctx, url, fetchdef)
400
+ }
401
+
402
+ max := f.exchange.retries
403
+ attempt := 0
404
+
405
+ for {
406
+ // The credential THIS attempt goes out with, captured before it
407
+ // leaves: it is what tells a stale refusal apart from a fresh one.
408
+ used := f.getcred()
409
+
410
+ res, err := inner(ctx, url, fetchdef)
411
+
412
+ if nil != err || attempt >= max || !f.spent(res) {
413
+ return res, err
414
+ }
415
+
416
+ // Another request may have bought a token while this one was in
417
+ // flight. Concurrent expiries share the in-flight purchase, but
418
+ // STAGGERED ones do not - so spend what is current before buying:
419
+ // a second exchange for a token that is already fresh is wasted,
420
+ // and on a provider that invalidates the previous credential on
421
+ // issuance it breaks the first request's own retry.
422
+ current := f.getcred()
423
+ token := ""
424
+
425
+ if "" != current && current != used {
426
+ token = current
427
+ } else {
428
+ bought, berr := f.buy()
429
+ if nil != berr {
430
+ // The purchase failed: answer with the API's own refusal
431
+ // rather than this one. The caller asked for data, and
432
+ // the refusal is the more useful of the two - the
433
+ // exchange error is a symptom.
434
+ return res, nil
435
+ }
436
+ // buy() published the token to the live options under the
437
+ // feature mutex - the PURCHASING goroutine is the only
438
+ // writer, so a burst of expired requests cannot race the
439
+ // map. Waiters use the returned value directly.
440
+ token = bought
441
+ }
442
+
443
+ f.reauth(fetchdef, token)
444
+
445
+ attempt++
446
+ }
447
+ }
448
+
449
+ func (f *SecretsFeature) spent(res any) bool {
450
+ status, is := fresStatus(res)
451
+ if !is {
452
+ return false
453
+ }
454
+ for _, s := range f.exchange.statuses {
455
+ if s == status {
456
+ return true
457
+ }
458
+ }
459
+ return false
460
+ }
461
+
462
+ // getcred reads the resolved credential under the feature mutex.
463
+ func (f *SecretsFeature) getcred() string {
464
+ f.mu.Lock()
465
+ v := f.cred
466
+ f.mu.Unlock()
467
+ return v
468
+ }
469
+
470
+ // Credential exposes the resolved credential (empty when none) - the
471
+ // state the transport injects; tests and callers read it here rather
472
+ // than from the options map, which this feature never mutates.
473
+ func (f *SecretsFeature) Credential() string {
474
+ return f.getcred()
475
+ }
476
+
477
+ func (f *SecretsFeature) reauth(fetchdef map[string]any, token string) {
478
+ headers, _ := fetchdef["headers"].(map[string]any)
479
+ if nil == headers {
480
+ return
481
+ }
482
+
483
+ // Suppressed auth means NO header, the same answer prepareAuth gives.
484
+ // Reached defensively - withrefresh does not retry at all when auth is
485
+ // nil - but this is the function that writes the credential, so it is
486
+ // where the rule has to hold.
487
+ // The options map is FROZEN after construction (this feature never
488
+ // writes it), so the raw read is safe on any goroutine.
489
+ rawauth := f.liveopts["auth"]
490
+ auth, _ := rawauth.(map[string]any)
491
+ if nil == rawauth || nil == auth {
492
+ delete(headers, "authorization")
493
+ return
494
+ }
495
+
496
+ prefix, _ := auth["prefix"].(string)
497
+ if "" == prefix {
498
+ headers["authorization"] = token
499
+ } else {
500
+ headers["authorization"] = prefix + " " + token
501
+ }
502
+ }
503
+
504
+ // buy an access token with the refresh token. Concurrent callers share the
505
+ // ONE in-flight purchase; the slot is cleared once settled, so the next
506
+ // expiry buys a fresh token rather than replaying this result.
507
+ func (f *SecretsFeature) buy() (string, error) {
508
+ // TEST MODE BUYS NOTHING. The test feature replaces the transport so
509
+ // no request leaves the process; an exchange here would be the one
510
+ // HTTP call it could not stop, and it would need a live token endpoint
511
+ // for a suite whose whole point is not needing one. A deterministic,
512
+ // obviously-fake token instead - the same answer makeOptions gives a
513
+ // required server variable, for the same reason.
514
+ if "live" != f.client.Mode {
515
+ token := "test-" + f.exchange.response
516
+ f.mu.Lock()
517
+ f.cred = token
518
+ f.mu.Unlock()
519
+ return token, nil
520
+ }
521
+
522
+ f.mu.Lock()
523
+ if buying := f.buying; nil != buying {
524
+ f.mu.Unlock()
525
+ <-buying.done
526
+ return buying.token, buying.err
527
+ }
528
+ buying := &secretsBuy{done: make(chan struct{})}
529
+ f.buying = buying
530
+ f.mu.Unlock()
531
+
532
+ token, err := f.buyonce()
533
+
534
+ f.mu.Lock()
535
+ buying.token = token
536
+ buying.err = err
537
+ f.buying = nil
538
+ if nil == err {
539
+ // Publish HERE, before the waiters wake: one writer, under the
540
+ // mutex - waiters consume the returned value.
541
+ f.cred = token
542
+ }
543
+ f.mu.Unlock()
544
+ close(buying.done)
545
+
546
+ return token, err
547
+ }
548
+
549
+ func (f *SecretsFeature) buyonce() (string, error) {
550
+ x := f.exchange
551
+
552
+ if "" == f.refresh {
553
+ return "", sekreto.Fail(
554
+ "secrets: no refresh token: the provider chain has no '" +
555
+ f.secretname + "', and feature.secrets.exchange.refresh is unset")
556
+ }
557
+
558
+ options := f.client.OptionsMap()
559
+
560
+ // The token endpoint is RELATIVE to the base, which already carries
561
+ // whatever account or tenant segment the server URL declares.
562
+ base, _ := options["base"].(string)
563
+ base = strings.TrimRight(base, "/")
564
+ url := base + "/" + strings.TrimLeft(x.path, "/")
565
+
566
+ system, _ := options["system"].(map[string]any)
567
+ fetch, _ := system["fetch"].(func(string, map[string]any) (map[string]any, error))
568
+
569
+ if nil == fetch {
570
+ // No custom transport supplied - the ordinary case. makeOptions
571
+ // leaves system.fetch unset, so the exchange gets its own raw
572
+ // HTTP path (mirroring the ts reference, whose system.fetch is
573
+ // initialized from the platform fetcher). Local and minimal on
574
+ // purpose: see the NOT-the-SDK-transport note below.
575
+ fetch = rawExchangeFetch
576
+ }
577
+
578
+ // The body is MARSHALLED, never concatenated: a refresh token (or a
579
+ // configured request-field name) carrying a quote, backslash or
580
+ // newline must arrive as that literal value, not as malformed JSON.
581
+ bodybytes, err := json.Marshal(map[string]string{x.request: f.refresh})
582
+ if nil != err {
583
+ return "", err
584
+ }
585
+
586
+ // Deliberately NOT the SDK transport. The transport is what this
587
+ // feature wraps, and sending the token request back through it would
588
+ // recurse on the first expiry - and would route the exchange through
589
+ // the test mock, which knows nothing about it.
590
+ res, err := fetch(url, map[string]any{
591
+ "method": x.method,
592
+ "headers": map[string]any{"content-type": "application/json"},
593
+ "body": string(bodybytes),
594
+ })
595
+ if nil != err {
596
+ return "", err
597
+ }
598
+
599
+ status := core.ToInt(res["status"])
600
+ if 200 > status || 300 <= status {
601
+ return "", sekreto.Fail(
602
+ "secrets: token exchange failed: " + strconv.Itoa(status) + " from " + url)
603
+ }
604
+
605
+ var body any
606
+ if jf, is := res["json"].(func() any); is {
607
+ body = jf()
608
+ } else {
609
+ body = res["body"]
610
+ }
611
+
612
+ token := ""
613
+ if bodymap, is := body.(map[string]any); is {
614
+ token, _ = bodymap[x.response].(string)
615
+ }
616
+
617
+ if "" == token {
618
+ return "", sekreto.Fail(
619
+ "secrets: token exchange returned no '" + x.response + "' field from " + url)
620
+ }
621
+
622
+ return token, nil
623
+ }
624
+
625
+ // rawExchangeFetch is the token-exchange transport of last resort: plain
626
+ // net/http, same result shape the system.fetch seam promises ("status" +
627
+ // "json"). It exists so an exchange works with ordinary SDK options -
628
+ // requiring a custom transport for the COMMON case would reject every
629
+ // live token purchase before a request was made.
630
+ func rawExchangeFetch(fullurl string, fetchdef map[string]any) (map[string]any, error) {
631
+ method, _ := fetchdef["method"].(string)
632
+ if "" == method {
633
+ method = "POST"
634
+ }
635
+
636
+ var body io.Reader
637
+ if raw, is := fetchdef["body"].(string); is && "" != raw {
638
+ body = strings.NewReader(raw)
639
+ }
640
+
641
+ req, err := http.NewRequest(method, fullurl, body)
642
+ if nil != err {
643
+ return nil, err
644
+ }
645
+ if headers, is := fetchdef["headers"].(map[string]any); is {
646
+ for k, v := range headers {
647
+ if vs, is := v.(string); is {
648
+ req.Header.Set(k, vs)
649
+ }
650
+ }
651
+ }
652
+
653
+ client := &http.Client{Timeout: 30 * time.Second}
654
+ res, err := client.Do(req)
655
+ if nil != err {
656
+ return nil, err
657
+ }
658
+ defer res.Body.Close()
659
+
660
+ raw, err := io.ReadAll(res.Body)
661
+ if nil != err {
662
+ return nil, err
663
+ }
664
+
665
+ return map[string]any{
666
+ "status": res.StatusCode,
667
+ "json": func() any {
668
+ var out any
669
+ if nil != json.Unmarshal(raw, &out) {
670
+ return nil
671
+ }
672
+ return out
673
+ },
674
+ }, nil
675
+ }