@voxgig/sdkgen 4.8.2 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/voxgig-sdkgen +1 -1
- package/dist/action/doctor.d.ts +1 -0
- package/dist/action/doctor.js +50 -2
- package/dist/action/doctor.js.map +1 -1
- package/dist/helpers/naming.js +4 -2
- package/dist/helpers/naming.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/model/sdkgen.aon +21 -0
- package/package.json +1 -1
- package/project/.sdk/model/feature/secrets.aon +120 -18
- package/project/.sdk/model/target/c.aon +10 -0
- package/project/.sdk/model/target/clojure.aon +13 -0
- package/project/.sdk/model/target/cpp.aon +10 -0
- package/project/.sdk/model/target/csharp.aon +9 -0
- package/project/.sdk/model/target/dart.aon +10 -0
- package/project/.sdk/model/target/elixir.aon +9 -0
- package/project/.sdk/model/target/go.aon +13 -0
- package/project/.sdk/model/target/java.aon +9 -0
- package/project/.sdk/model/target/js.aon +7 -0
- package/project/.sdk/model/target/kotlin.aon +9 -0
- package/project/.sdk/model/target/lean.aon +17 -0
- package/project/.sdk/model/target/lua.aon +8 -0
- package/project/.sdk/model/target/ocaml.aon +9 -0
- package/project/.sdk/model/target/perl.aon +8 -0
- package/project/.sdk/model/target/php.aon +8 -0
- package/project/.sdk/model/target/py.aon +13 -0
- package/project/.sdk/model/target/rb.aon +8 -0
- package/project/.sdk/model/target/rust.aon +10 -0
- package/project/.sdk/model/target/scala.aon +21 -2
- package/project/.sdk/model/target/swift.aon +18 -0
- package/project/.sdk/model/target/ts.aon +13 -0
- package/project/.sdk/model/target/zig.aon +9 -0
- package/project/.sdk/src/cmp/clojure/Package_clojure.ts +9 -2
- package/project/.sdk/src/cmp/cpp/Gitignore_cpp.ts +3 -0
- package/project/.sdk/src/cmp/dart/Test_dart.ts +2 -0
- package/project/.sdk/src/cmp/elixir/Package_elixir.ts +4 -1
- package/project/.sdk/src/cmp/go/Config_go.ts +59 -2
- package/project/.sdk/src/cmp/go/Main_go.ts +8 -2
- package/project/.sdk/src/cmp/java/Test_java.ts +6 -5
- package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +6 -5
- package/project/.sdk/src/cmp/lean/Package_lean.ts +23 -0
- package/project/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +1 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +1 -0
- package/project/.sdk/src/cmp/ocaml/Gitignore_ocaml.ts +1 -0
- package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +7 -3
- package/project/.sdk/src/cmp/py/Config_py.ts +82 -1
- package/project/.sdk/src/cmp/py/Main_py.ts +44 -0
- package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +2 -0
- package/project/.sdk/src/cmp/swift/Main_swift.ts +10 -0
- package/project/.sdk/src/cmp/swift/Package_swift.ts +13 -1
- package/project/.sdk/src/cmp/ts/Config_ts.ts +42 -17
- package/project/.sdk/src/cmp/ts/fragment/Config.data.fragment.ts +13 -1
- package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +13 -1
- package/project/.sdk/src/cmp/zig/Package_zig.ts +15 -11
- package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +3 -3
- package/project/.sdk/src/cmp/zig/fragment/EntityListOp.fragment.zig +3 -3
- package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +3 -3
- package/project/.sdk/src/cmp/zig/utility_zig.ts +50 -1
- package/project/.sdk/tm/c/Makefile +38 -3
- package/project/.sdk/tm/c/tests/omni_resolver.h +361 -0
- package/project/.sdk/tm/c/tests/omni_smoke_test.c +237 -0
- package/project/.sdk/tm/c/tests/primary_corpus_test.c +205 -284
- package/project/.sdk/tm/c/tests/struct_corpus_test.c +292 -212
- package/project/.sdk/tm/c/tests/vendor/omni/json.c +811 -0
- package/project/.sdk/tm/c/tests/vendor/omni/omni.h +240 -0
- package/project/.sdk/tm/c/tests/vendor/omni/runner.c +940 -0
- package/project/.sdk/tm/c/tests/vendor/omni/util.c +351 -0
- package/project/.sdk/tm/c/utility/struct/utility.c +7 -2
- package/project/.sdk/tm/clojure/test/sdk/test/omni.clj +401 -0
- package/project/.sdk/tm/clojure/test/sdk/test/omni_smoke.clj +81 -0
- package/project/.sdk/tm/clojure/test/sdk/test/primary.clj +92 -58
- package/project/.sdk/tm/clojure/test/sdk/test/struct_corpus.clj +122 -149
- package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +8 -3
- package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/json.clj +145 -0
- package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/runner.clj +445 -0
- package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/util.clj +145 -0
- package/project/.sdk/tm/cpp/Makefile +5 -1
- package/project/.sdk/tm/cpp/test/omni_resolver.hpp +473 -0
- package/project/.sdk/tm/cpp/test/omni_smoke_test.cpp +209 -0
- package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +243 -184
- package/project/.sdk/tm/cpp/test/runner_support.hpp +68 -181
- package/project/.sdk/tm/cpp/test/struct_corpus_test.cpp +183 -56
- package/project/.sdk/tm/cpp/test/vendor/omni/json.hpp +406 -0
- package/project/.sdk/tm/cpp/test/vendor/omni/omni.hpp +751 -0
- package/project/.sdk/tm/cpp/test/vendor/omni/util.hpp +256 -0
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +7 -1
- package/project/.sdk/tm/csharp/test/OmniResolver.cs +491 -0
- package/project/.sdk/tm/csharp/test/OmniSmokeTest.cs +106 -0
- package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +299 -316
- package/project/.sdk/tm/csharp/test/Runner.cs +104 -269
- package/project/.sdk/tm/csharp/test/StructUtilityTest.cs +535 -724
- package/project/.sdk/tm/csharp/test/vendor/omni/Runner.cs +864 -0
- package/project/.sdk/tm/csharp/test/vendor/omni/Util.cs +347 -0
- package/project/.sdk/tm/csharp/utility/MakeSpec.cs +3 -1
- package/project/.sdk/tm/csharp/utility/PrepareMethod.cs +6 -1
- package/project/.sdk/tm/csharp/utility/struct/Struct.cs +21 -5
- package/project/.sdk/tm/dart/test/omni.dart +520 -0
- package/project/.sdk/tm/dart/test/omni_smoke_test.dart +143 -0
- package/project/.sdk/tm/dart/test/primary_test.dart +86 -28
- package/project/.sdk/tm/dart/test/struct_test.dart +438 -11
- package/project/.sdk/tm/dart/test/vendor/omni/omni.dart +7 -0
- package/project/.sdk/tm/dart/test/vendor/omni/runner.dart +653 -0
- package/project/.sdk/tm/dart/test/vendor/omni/util.dart +232 -0
- package/project/.sdk/tm/elixir/Makefile +11 -3
- package/project/.sdk/tm/elixir/test/omni_smoke_test.exs +117 -0
- package/project/.sdk/tm/elixir/test/primary_utility_test.exs +341 -16
- package/project/.sdk/tm/elixir/test/struct_corpus_test.exs +554 -9
- package/project/.sdk/tm/elixir/test/support/omni.ex +377 -0
- package/project/.sdk/tm/elixir/test/vendor/omni/json.ex +122 -0
- package/project/.sdk/tm/elixir/test/vendor/omni/runner.ex +623 -0
- package/project/.sdk/tm/elixir/test/vendor/omni/util.ex +187 -0
- package/project/.sdk/tm/go/core/context.go +32 -16
- package/project/.sdk/tm/go/feature/secrets/plugin/capability.go +261 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/catalog.go +78 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/config.go +652 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/depend.go +250 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/env.go +194 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/export.go +80 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/graph.go +238 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/host.go +1575 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/order.go +248 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/point.go +184 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/ref.go +123 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/resolve.go +79 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/types.go +296 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/util.go +87 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/version.go +161 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/aws/aws.go +292 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/aws/sigv4.go +201 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/azuresecrets/azuresecrets.go +187 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/boru/boru.go +184 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/doppler/doppler.go +114 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/gcpsecrets/gcpsecrets.go +156 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/hashicorp/hashicorp.go +208 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/httpjson/httpjson.go +241 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/infisical/infisical.go +150 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/onepassword/onepassword.go +152 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/secretspec/secretspec.go +143 -0
- package/project/.sdk/tm/go/feature/secrets/sekreto/addr.go +120 -0
- package/project/.sdk/tm/go/feature/secrets/sekreto/providers.go +442 -0
- package/project/.sdk/tm/go/feature/secrets/sekreto/sekreto.go +714 -0
- package/project/.sdk/tm/go/feature/secrets_feature.go +675 -0
- package/project/.sdk/tm/go/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/go/test/feature/secrets/secrets_feature_test.go +799 -0
- package/project/.sdk/tm/go/test/omni/omni.go +902 -0
- package/project/.sdk/tm/go/test/omni/util.go +381 -0
- package/project/.sdk/tm/go/test/omniresolver_test.go +748 -0
- package/project/.sdk/tm/go/test/omnismoke_test.go +112 -0
- package/project/.sdk/tm/go/test/primary_utility_test.go +123 -191
- package/project/.sdk/tm/go/test/struct_utility_test.go +323 -16
- package/project/.sdk/tm/go/test/testsupport_test.go +294 -0
- package/project/.sdk/tm/go/utility/make_options.go +8 -1
- package/project/.sdk/tm/go/utility/prepare_method.go +5 -1
- package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +2 -2
- package/project/.sdk/tm/java/test/OmniResolver.java +355 -0
- package/project/.sdk/tm/java/test/OmniSmokeTest.java +99 -0
- package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +254 -280
- package/project/.sdk/tm/java/test/RunnerSupport.java +9 -194
- package/project/.sdk/tm/java/test/StructCorpusTest.java +119 -42
- package/project/.sdk/tm/java/test/vendor/omni/Json.java +287 -0
- package/project/.sdk/tm/java/test/vendor/omni/Runner.java +851 -0
- package/project/.sdk/tm/java/test/vendor/omni/Util.java +322 -0
- package/project/.sdk/tm/java/utility/MakeSpec.java +3 -1
- package/project/.sdk/tm/java/utility/PrepareMethod.java +5 -5
- package/project/.sdk/tm/java/utility/struct/Struct.java +17 -4
- package/project/.sdk/tm/js/src/utility/StructUtility.js +3 -3
- package/project/.sdk/tm/js/test/omni.js +251 -0
- package/project/.sdk/tm/js/test/omni.test.js +105 -0
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +6 -2
- package/project/.sdk/tm/js/test/utility/StructUtility.test.js +27 -2
- package/project/.sdk/tm/js/test/vendor/omni/index.js +77 -0
- package/project/.sdk/tm/js/test/vendor/omni/runner.js +628 -0
- package/project/.sdk/tm/js/test/vendor/omni/util.js +229 -0
- package/project/.sdk/tm/kotlin/core/Utility.kt +1 -1
- package/project/.sdk/tm/kotlin/test/OmniResolver.kt +343 -0
- package/project/.sdk/tm/kotlin/test/OmniSmokeTest.kt +100 -0
- package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +244 -262
- package/project/.sdk/tm/kotlin/test/RunnerSupport.kt +9 -178
- package/project/.sdk/tm/kotlin/test/StructCorpusTest.kt +121 -32
- package/project/.sdk/tm/kotlin/test/vendor/omni/Json.kt +264 -0
- package/project/.sdk/tm/kotlin/test/vendor/omni/Runner.kt +615 -0
- package/project/.sdk/tm/kotlin/test/vendor/omni/Util.kt +139 -0
- package/project/.sdk/tm/kotlin/utility/MakeSpecUrl.kt +6 -3
- package/project/.sdk/tm/kotlin/utility/Prepare.kt +6 -6
- package/project/.sdk/tm/kotlin/utility/struct/Struct.kt +18 -2
- package/project/.sdk/tm/lean/Makefile +12 -5
- package/project/.sdk/tm/lean/src/SdkUtility.lean +14 -1
- package/project/.sdk/tm/lean/test/OmniResolver.lean +358 -0
- package/project/.sdk/tm/lean/test/OmniSmoke.lean +174 -0
- package/project/.sdk/tm/lean/test/StructCorpus.lean +245 -574
- package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +155 -291
- package/project/.sdk/tm/lean/test/vendor/omni/Omni.lean +997 -0
- package/project/.sdk/tm/lua/test/omni.lua +456 -0
- package/project/.sdk/tm/lua/test/omni_smoke_test.lua +103 -0
- package/project/.sdk/tm/lua/test/primary_utility_test.lua +250 -509
- package/project/.sdk/tm/lua/test/struct_utility_test.lua +161 -70
- package/project/.sdk/tm/lua/test/vendor/omni/json.lua +268 -0
- package/project/.sdk/tm/lua/test/vendor/omni/regex.lua +385 -0
- package/project/.sdk/tm/lua/test/vendor/omni/runner.lua +641 -0
- package/project/.sdk/tm/lua/test/vendor/omni/util.lua +282 -0
- package/project/.sdk/tm/lua/utility/prepare_method.lua +5 -1
- package/project/.sdk/tm/lua/utility/struct/regex.lua +663 -0
- package/project/.sdk/tm/lua/utility/struct/struct.lua +660 -420
- package/project/.sdk/tm/ocaml/Makefile +37 -12
- package/project/.sdk/tm/ocaml/test/omni_resolver.ml +284 -0
- package/project/.sdk/tm/ocaml/test/omni_smoke_test.ml +169 -0
- package/project/.sdk/tm/ocaml/test/primary_utility_test.ml +84 -100
- package/project/.sdk/tm/ocaml/test/struct_corpus.ml +225 -201
- package/project/.sdk/tm/ocaml/test/vendor/omni/omni.ml +1157 -0
- package/project/.sdk/tm/perl/lib/Voxgig/Struct.pm +88 -12
- package/project/.sdk/tm/perl/t/omni.pm +647 -0
- package/project/.sdk/tm/perl/t/omni_smoke.t +87 -0
- package/project/.sdk/tm/perl/t/primary_utility.t +189 -487
- package/project/.sdk/tm/perl/t/struct_utility.t +455 -389
- package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Runner.pm +649 -0
- package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Util.pm +253 -0
- package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni.pm +24 -0
- package/project/.sdk/tm/perl/utility/prepare_method.pm +7 -2
- package/project/.sdk/tm/php/test/Omni.php +691 -0
- package/project/.sdk/tm/php/test/OmniSmokeTest.php +93 -0
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +210 -571
- package/project/.sdk/tm/php/test/StructUtilityTest.php +320 -342
- package/project/.sdk/tm/php/test/vendor/omni/Runner.php +644 -0
- package/project/.sdk/tm/php/test/vendor/omni/Util.php +283 -0
- package/project/.sdk/tm/php/utility/MakeSpec.php +10 -3
- package/project/.sdk/tm/php/utility/PrepareBody.php +7 -1
- package/project/.sdk/tm/php/utility/PrepareMethod.php +6 -2
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/__init__.py +36 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/capability.py +141 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/catalog.py +50 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/config.py +333 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/depend.py +198 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/env.py +147 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/export.py +52 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/graph.py +139 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/host.py +1053 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/order.py +171 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/point.py +95 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/ref.py +116 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/resolve.py +59 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/types.py +87 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/version.py +112 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/__init__.py +76 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/addr.py +116 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/aws.py +192 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/azuresecrets.py +120 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/boru.py +140 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/doppler.py +62 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/gcpsecrets.py +101 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/hashicorp.py +151 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/httpjson.py +115 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/infisical.py +90 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/onepassword.py +101 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/secretspec.py +119 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/sigv4.py +125 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/providers.py +211 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/sekreto.py +475 -0
- package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +467 -0
- package/project/.sdk/tm/py/pkg/utility/prepare_method.py +5 -1
- package/project/.sdk/tm/py/pkg/utility/voxgig_struct/__init__.py +0 -2
- package/project/.sdk/tm/py/pkg/utility/voxgig_struct/voxgig_struct.py +780 -529
- package/project/.sdk/tm/py/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/py/test/feature/__init__.py +0 -0
- package/project/.sdk/tm/py/test/feature/secrets/__init__.py +0 -0
- package/project/.sdk/tm/py/test/feature/secrets/test_secrets.py +337 -0
- package/project/.sdk/tm/py/test/omni.py +415 -0
- package/project/.sdk/tm/py/test/test_omni_smoke.py +74 -0
- package/project/.sdk/tm/py/test/test_primary_utility.py +144 -668
- package/project/.sdk/tm/py/test/test_struct_utility.py +74 -27
- package/project/.sdk/tm/py/test/voxgig_omni/__init__.py +62 -0
- package/project/.sdk/tm/py/test/voxgig_omni/runner.py +580 -0
- package/project/.sdk/tm/py/test/voxgig_omni/util.py +252 -0
- package/project/.sdk/tm/rb/test/omni.rb +505 -0
- package/project/.sdk/tm/rb/test/omni_smoke_test.rb +72 -0
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +174 -560
- package/project/.sdk/tm/rb/test/struct_utility_test.rb +13 -7
- package/project/.sdk/tm/rb/test/vendor/omni/runner.rb +493 -0
- package/project/.sdk/tm/rb/test/vendor/omni/util.rb +199 -0
- package/project/.sdk/tm/rb/test/vendor/omni/voxgig_omni.rb +15 -0
- package/project/.sdk/tm/rb/utility/prepare_method.rb +5 -1
- package/project/.sdk/tm/rust/tests/common/mod.rs +19 -242
- package/project/.sdk/tm/rust/tests/omni_resolver/mod.rs +888 -0
- package/project/.sdk/tm/rust/tests/omni_smoke_test.rs +286 -0
- package/project/.sdk/tm/rust/tests/primary_utility_test.rs +318 -312
- package/project/.sdk/tm/rust/tests/struct_utility_test.rs +66 -28
- package/project/.sdk/tm/rust/tests/vendor/omni/json.rs +412 -0
- package/project/.sdk/tm/rust/tests/vendor/omni/mod.rs +38 -0
- package/project/.sdk/tm/rust/tests/vendor/omni/regex.rs +392 -0
- package/project/.sdk/tm/rust/tests/vendor/omni/runner.rs +1001 -0
- package/project/.sdk/tm/rust/tests/vendor/omni/util.rs +161 -0
- package/project/.sdk/tm/rust/utility/prepare_method.rs +5 -1
- package/project/.sdk/tm/scala/Makefile +16 -6
- package/project/.sdk/tm/scala/sdktest/OmniResolver.scala +497 -0
- package/project/.sdk/tm/scala/sdktest/OmniSmoke.scala +192 -0
- package/project/.sdk/tm/scala/sdktest/PrimaryCorpus.scala +47 -19
- package/project/.sdk/tm/scala/sdktest/StructCorpus.scala +0 -0
- package/project/.sdk/tm/scala/sdktest/vendor/omni/Json.scala +229 -0
- package/project/.sdk/tm/scala/sdktest/vendor/omni/Runner.scala +552 -0
- package/project/.sdk/tm/scala/sdktest/vendor/omni/Util.scala +104 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Constants.swift +10 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Inject.swift +28 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Injection.swift +5 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Minor.swift +4 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Validate.swift +15 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +6 -1
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/OmniResolver.swift +474 -0
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/OmniSmokeTest.swift +107 -0
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +141 -178
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/Runner.swift +17 -113
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/StructUtilityTest.swift +295 -446
- package/project/.sdk/tm/swift/Tests/vendor/omni/Json.swift +364 -0
- package/project/.sdk/tm/swift/Tests/vendor/omni/Runner.swift +730 -0
- package/project/.sdk/tm/swift/Tests/vendor/omni/Util.swift +162 -0
- package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +7 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Capability.ts +148 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Catalog.ts +55 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Config.ts +344 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Depend.ts +205 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Env.ts +138 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Export.ts +46 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/FeatureHost.ts +349 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Graph.ts +181 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Host.ts +1132 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Order.ts +177 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Point.ts +119 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Ref.ts +102 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Resolve.ts +61 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Types.ts +112 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Version.ts +100 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/index.ts +37 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +163 -30
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +27 -22
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/aws.ts +26 -36
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/azuresecrets.ts +19 -21
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/boru.ts +36 -17
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/doppler.ts +14 -21
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/gcpsecrets.ts +27 -27
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/hashicorp.ts +25 -39
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/httpjson.ts +99 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/infisical.ts +14 -16
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/onepassword.ts +15 -22
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/secretspec.ts +98 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{Sigv4.ts → plugins/sigv4.ts} +7 -6
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/addr.ts +97 -23
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/builtin.ts +37 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/dotenv.ts +4 -17
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/env.ts +4 -16
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/file.ts +11 -25
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/memory.ts +6 -23
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/support.ts +106 -39
- package/project/.sdk/tm/ts/src/utility/StructUtility.ts +3 -3
- package/project/.sdk/tm/ts/test/omni.ts +104 -32
- package/project/.sdk/tm/ts/test/utility/StructUtility.test.ts +27 -0
- package/project/.sdk/tm/ts/test/vendor/omni/Runner.ts +32 -5
- package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +2 -2
- package/project/.sdk/tm/ts/test/vendor/omni/index.ts +2 -2
- package/project/.sdk/tm/zig/Makefile +15 -1
- package/project/.sdk/tm/zig/build.zig +23 -5
- package/project/.sdk/tm/zig/core/helpers.zig +52 -11
- package/project/.sdk/tm/zig/core/mem.zig +17 -1
- package/project/.sdk/tm/zig/core/utility.zig +23 -19
- package/project/.sdk/tm/zig/feature/audit.zig +2 -2
- package/project/.sdk/tm/zig/feature/cache.zig +2 -2
- package/project/.sdk/tm/zig/feature/debug.zig +5 -5
- package/project/.sdk/tm/zig/feature/netsim.zig +2 -2
- package/project/.sdk/tm/zig/feature/paging.zig +2 -2
- package/project/.sdk/tm/zig/feature/proxy.zig +15 -8
- package/project/.sdk/tm/zig/feature/streaming.zig +5 -5
- package/project/.sdk/tm/zig/feature/support.zig +3 -3
- package/project/.sdk/tm/zig/feature/telemetry.zig +5 -5
- package/project/.sdk/tm/zig/feature/test.zig +10 -5
- package/project/.sdk/tm/zig/test/fh.zig +10 -10
- package/project/.sdk/tm/zig/test/gotcha_test.zig +5 -5
- package/project/.sdk/tm/zig/test/omniresolver.zig +515 -0
- package/project/.sdk/tm/zig/test/omnismoke_test.zig +284 -0
- package/project/.sdk/tm/zig/test/pipeline_test.zig +8 -8
- package/project/.sdk/tm/zig/test/primary_utility_test.zig +145 -155
- package/project/.sdk/tm/zig/test/struct_corpus.zig +264 -187
- package/project/.sdk/tm/zig/test/vendor/omni/omni.zig +1314 -0
- package/project/.sdk/tm/zig/test/vendor/omni/regex.zig +446 -0
- package/project/.sdk/tm/zig/utility/voxgigstruct/regex.zig +7 -4
- package/project/.sdk/tm/zig/utility/voxgigstruct/struct.zig +356 -157
- package/project/sdkgen-package.json +1 -1
- package/src/action/doctor.ts +66 -2
- package/src/helpers/naming.ts +4 -2
- package/project/.sdk/tm/c/tests/runner.h +0 -274
- package/project/.sdk/tm/cpp/test/struct_runner.hpp +0 -314
- package/project/.sdk/tm/csharp/test/StructRunner.cs +0 -276
- package/project/.sdk/tm/dart/test/runner.dart +0 -406
- package/project/.sdk/tm/dart/test/struct_corpus.dart +0 -531
- package/project/.sdk/tm/elixir/test/support/struct_corpus.ex +0 -1088
- package/project/.sdk/tm/go/test/runner_test.go +0 -629
- package/project/.sdk/tm/go/test/struct_runner_test.go +0 -1094
- package/project/.sdk/tm/java/test/StructRunner.java +0 -281
- package/project/.sdk/tm/js/test/runner.js +0 -387
- package/project/.sdk/tm/kotlin/test/StructRunner.kt +0 -177
- package/project/.sdk/tm/lua/test/struct_runner.lua +0 -602
- package/project/.sdk/tm/ocaml/test/corpus_runner.ml +0 -185
- package/project/.sdk/tm/perl/t/struct_runner.pm +0 -275
- package/project/.sdk/tm/php/test/StructRunner.php +0 -275
- package/project/.sdk/tm/py/test/struct_runner.py +0 -411
- package/project/.sdk/tm/rb/test/struct_runner.rb +0 -309
- package/project/.sdk/tm/rust/tests/struct_runner/mod.rs +0 -424
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/Registry.ts +0 -90
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/http.ts +0 -66
- package/project/.sdk/tm/ts/test/vendor/omni/compat.ts +0 -188
- package/project/.sdk/tm/zig/test/struct_runner.zig +0 -464
|
@@ -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
|
+
}
|
|
File without changes
|