@voxgig/sdkgen 4.8.2 → 4.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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/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 +209 -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 +151 -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 +439 -0
- package/project/.sdk/tm/go/feature/secrets/sekreto/sekreto.go +685 -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 +897 -0
- package/project/.sdk/tm/go/test/omni/util.go +360 -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 +613 -0
- package/project/.sdk/tm/js/test/vendor/omni/util.js +212 -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 +74 -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 +152 -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 +92 -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 +455 -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 +566 -0
- package/project/.sdk/tm/py/test/voxgig_omni/util.py +237 -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/test/primary_utility_test.zig +1 -1
- package/project/.sdk/tm/zig/test/struct_runner.zig +5 -4
- 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
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
# ProjectName SDK secrets feature
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
import json
|
|
5
|
+
import urllib.error
|
|
6
|
+
import urllib.request
|
|
7
|
+
|
|
8
|
+
from projectname_sdk.utility.voxgig_struct import voxgig_struct as vs
|
|
9
|
+
from projectname_sdk.feature.base_feature import ProjectNameBaseFeature
|
|
10
|
+
from projectname_sdk.feature.secrets.voxgig_sekreto import Sekreto, envkey
|
|
11
|
+
# The plugin DEFINITIONS the model selected for this feature, emitted by
|
|
12
|
+
# config generically from the catalogue's active `plugin.def` entries.
|
|
13
|
+
# Upstream sekreto's contract since the registry was retired: a kind not
|
|
14
|
+
# passed in `plugins` is unknown to that Sekreto, so the model's choice of
|
|
15
|
+
# plugin groups IS the SDK's provider vocabulary.
|
|
16
|
+
from projectname_sdk.config import FEATURE_PLUGINS
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class _LiveProvider:
|
|
20
|
+
"""A custom provider given as a MAP of callables, adapted to the
|
|
21
|
+
object shape sekreto's live-provider check reads.
|
|
22
|
+
|
|
23
|
+
ts accepts `{ lookup() {...}, describe() {...} }` verbatim because a
|
|
24
|
+
JS object literal survives the options clone with its functions
|
|
25
|
+
intact. python's vs.clone flattens a class INSTANCE to a plain dict of
|
|
26
|
+
its instance attributes (methods lost), so the dict-of-callables IS
|
|
27
|
+
the shape that reaches this feature - the exact parallel of the ts
|
|
28
|
+
contract - and this adapter turns it back into a provider."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, spec):
|
|
31
|
+
self._spec = spec
|
|
32
|
+
|
|
33
|
+
def lookup(self, name):
|
|
34
|
+
return self._spec["lookup"](name)
|
|
35
|
+
|
|
36
|
+
def describe(self):
|
|
37
|
+
describe = self._spec.get("describe")
|
|
38
|
+
return describe() if callable(describe) else "custom"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _provider_entry(p):
|
|
42
|
+
if isinstance(p, dict) and callable(p.get("lookup")):
|
|
43
|
+
return _LiveProvider(p)
|
|
44
|
+
return p
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# Secret access via a vendored voxgig_sekreto provider chain, and the
|
|
48
|
+
# access-token exchange some APIs require on top of it. A port of the ts
|
|
49
|
+
# reference (tm/ts/src/feature/secrets/SecretsFeature.ts) - semantics
|
|
50
|
+
# must match, seam for seam.
|
|
51
|
+
#
|
|
52
|
+
# The SDK's `apikey` option keeps exactly its old meaning: an explicit
|
|
53
|
+
# credential given in code. This feature makes it ONE SOURCE among several
|
|
54
|
+
# rather than the only one: when active, the apikey is resolved through a
|
|
55
|
+
# sekreto chain in which the explicit option (when set) is the FIRST
|
|
56
|
+
# provider - a `memory` store named 'options' - so an explicit value
|
|
57
|
+
# always wins, by sekreto's own first-hit rule rather than by special-case
|
|
58
|
+
# logic. When the option is unset, the remaining providers (env, dotenv, a
|
|
59
|
+
# vault) are asked in order, and moving a credential from code to a vault
|
|
60
|
+
# becomes a configuration change.
|
|
61
|
+
#
|
|
62
|
+
# SOME APIs will not take a long-lived credential at all. What the chain
|
|
63
|
+
# resolves is then a REFRESH token, which buys a short-lived ACCESS token
|
|
64
|
+
# from a token endpoint; the access token is what every request carries,
|
|
65
|
+
# and it expires. `exchange.active` turns that round trip on: the resolved
|
|
66
|
+
# secret is POSTed to `exchange.path` (relative to options.base), the
|
|
67
|
+
# access token from the response is written to options.apikey, and a
|
|
68
|
+
# response in `exchange.statuses` (401) buys another and retries once.
|
|
69
|
+
#
|
|
70
|
+
# That last part is why this feature wraps the transport. Expiry is only
|
|
71
|
+
# ever discovered from a RESPONSE, and the transport is the one place a
|
|
72
|
+
# response can be seen before the operation pipeline turns it into a
|
|
73
|
+
# result. With the exchange off, nothing is wrapped.
|
|
74
|
+
#
|
|
75
|
+
# WHERE ts RESOLVES ASYNCHRONOUSLY, PYTHON IS SYNC THROUGHOUT: sekreto's
|
|
76
|
+
# python port does blocking IO, so the PreSpec hook resolves in place and
|
|
77
|
+
# ts's shared in-flight promise degenerates to the resolved/cache flags
|
|
78
|
+
# below. The observable rules are unchanged: one resolution serves every
|
|
79
|
+
# op while caching is on, `cache: False` asks the chain again each time,
|
|
80
|
+
# and a provider ERROR raises and fails the op - sekreto's miss-vs-error
|
|
81
|
+
# rule: never fall through to an unauthenticated request because a store
|
|
82
|
+
# was broken. prepare_auth itself is untouched: PreSpec runs before
|
|
83
|
+
# make_spec on every entity op, so the resolved value lands in the live
|
|
84
|
+
# options where prepare_auth already looks.
|
|
85
|
+
class ProjectNameSecretsFeature(ProjectNameBaseFeature):
|
|
86
|
+
def __init__(self):
|
|
87
|
+
super().__init__()
|
|
88
|
+
self.version = "0.1.0"
|
|
89
|
+
self.name = "secrets"
|
|
90
|
+
self.active = True
|
|
91
|
+
|
|
92
|
+
self._client = None
|
|
93
|
+
self._sekreto = None
|
|
94
|
+
self._secretname = "apikey"
|
|
95
|
+
self._resolved = False
|
|
96
|
+
self._lastset = None
|
|
97
|
+
self._cache = True
|
|
98
|
+
|
|
99
|
+
# Exchange state. `_exchange` is the resolved config (None when
|
|
100
|
+
# off) and `_refresh` the credential the chain gave us.
|
|
101
|
+
self._exchange = None
|
|
102
|
+
self._refresh = None
|
|
103
|
+
|
|
104
|
+
# Sync by contract: build the chain only, never look anything up here.
|
|
105
|
+
def init(self, ctx, fopts):
|
|
106
|
+
client = ctx.client
|
|
107
|
+
options = ctx.options if isinstance(ctx.options, dict) else {}
|
|
108
|
+
fopts = fopts if isinstance(fopts, dict) else {}
|
|
109
|
+
|
|
110
|
+
self._client = client
|
|
111
|
+
|
|
112
|
+
name = fopts.get("name")
|
|
113
|
+
self._secretname = name if isinstance(name, str) and "" != name \
|
|
114
|
+
else "apikey"
|
|
115
|
+
|
|
116
|
+
# Exchange config, normalised once. None when off, so every later
|
|
117
|
+
# decision is a None check rather than a repeated active test.
|
|
118
|
+
xopts = fopts.get("exchange")
|
|
119
|
+
if isinstance(xopts, dict) and xopts.get("active") is True:
|
|
120
|
+
self._exchange = {
|
|
121
|
+
"path": xopts.get("path")
|
|
122
|
+
if isinstance(xopts.get("path"), str) else "auth/token",
|
|
123
|
+
"method": xopts.get("method")
|
|
124
|
+
if isinstance(xopts.get("method"), str) else "POST",
|
|
125
|
+
"request": xopts.get("request")
|
|
126
|
+
if isinstance(xopts.get("request"), str) else "refresh_token",
|
|
127
|
+
"response": xopts.get("response")
|
|
128
|
+
if isinstance(xopts.get("response"), str) else "access_token",
|
|
129
|
+
"statuses": xopts.get("statuses")
|
|
130
|
+
if isinstance(xopts.get("statuses"), list) else [401],
|
|
131
|
+
"retries": xopts.get("retries")
|
|
132
|
+
if isinstance(xopts.get("retries"), (int, float))
|
|
133
|
+
and not isinstance(xopts.get("retries"), bool) else 1,
|
|
134
|
+
}
|
|
135
|
+
else:
|
|
136
|
+
self._exchange = None
|
|
137
|
+
|
|
138
|
+
providers = []
|
|
139
|
+
|
|
140
|
+
# The explicit credential, when set, is the first store in the
|
|
141
|
+
# chain.
|
|
142
|
+
#
|
|
143
|
+
# WHICH option that is depends on the exchange. Without one, the
|
|
144
|
+
# secret being resolved IS the credential the transport sends, so
|
|
145
|
+
# `apikey` is it. With one, the secret is a REFRESH token and
|
|
146
|
+
# `apikey` means the opposite thing - an access token the caller
|
|
147
|
+
# already holds - so the explicit seat belongs to
|
|
148
|
+
# `exchange.refresh`, and apikey is left alone to serve as the
|
|
149
|
+
# starting access token (see _resolve_once below).
|
|
150
|
+
if self._exchange is None:
|
|
151
|
+
explicit = options.get("apikey")
|
|
152
|
+
else:
|
|
153
|
+
explicit = xopts.get("refresh") if isinstance(xopts, dict) else None
|
|
154
|
+
|
|
155
|
+
if isinstance(explicit, str) and "" != explicit:
|
|
156
|
+
providers.append({
|
|
157
|
+
"kind": "memory",
|
|
158
|
+
"name": "options",
|
|
159
|
+
"values": {envkey(self._secretname): explicit},
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
for p in (fopts.get("providers") or []):
|
|
163
|
+
providers.append(_provider_entry(p))
|
|
164
|
+
|
|
165
|
+
self._cache = fopts.get("cache") is not False
|
|
166
|
+
|
|
167
|
+
self._sekreto = Sekreto({
|
|
168
|
+
"providers": providers,
|
|
169
|
+
"plugins": FEATURE_PLUGINS.get(self.name) or [],
|
|
170
|
+
"cache": self._cache,
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
# Seam for ProjectNameSDK.prepare() (no feature hooks on that
|
|
174
|
+
# path) and for callers wanting the live Sekreto.
|
|
175
|
+
client._secrets = self
|
|
176
|
+
|
|
177
|
+
# Wrap the transport ONLY when there is an exchange to defend. A
|
|
178
|
+
# spent access token is discovered from the response, and this is
|
|
179
|
+
# the one place a response can be seen and the request tried
|
|
180
|
+
# again.
|
|
181
|
+
if self._exchange is not None:
|
|
182
|
+
utility = ctx.utility
|
|
183
|
+
inner = utility.fetcher
|
|
184
|
+
|
|
185
|
+
def secrets_fetcher(fctx, fullurl, fetchdef):
|
|
186
|
+
return self._with_refresh(fctx, fullurl, fetchdef, inner)
|
|
187
|
+
|
|
188
|
+
utility.fetcher = secrets_fetcher
|
|
189
|
+
|
|
190
|
+
# The LIVE Sekreto instance, for callers who want arbitrary secrets or
|
|
191
|
+
# redaction:
|
|
192
|
+
#
|
|
193
|
+
# sdk._secrets.sekreto().get('db.password')
|
|
194
|
+
# sdk._secrets.sekreto().redact(logline)
|
|
195
|
+
#
|
|
196
|
+
# Never a clone: sekreto holds provider state (caches, vault leases)
|
|
197
|
+
# that has to stay live to be worth anything.
|
|
198
|
+
def sekreto(self):
|
|
199
|
+
return self._sekreto
|
|
200
|
+
|
|
201
|
+
def PreSpec(self, _ctx):
|
|
202
|
+
return self.resolve()
|
|
203
|
+
|
|
204
|
+
# Resolve the apikey before the first request. A successful resolve is
|
|
205
|
+
# reused while caching is on; with `cache: False` the chain is asked
|
|
206
|
+
# again on every call - holding the first answer forever would make
|
|
207
|
+
# the documented option a lie. A provider ERROR raises (fails the op)
|
|
208
|
+
# and leaves nothing cached, so a transient vault outage does not
|
|
209
|
+
# poison the client after the vault recovers.
|
|
210
|
+
def resolve(self):
|
|
211
|
+
if self._resolved and self._cache:
|
|
212
|
+
return
|
|
213
|
+
self._resolve_once()
|
|
214
|
+
self._resolved = True
|
|
215
|
+
|
|
216
|
+
def _resolve_once(self):
|
|
217
|
+
if self._sekreto is None:
|
|
218
|
+
return
|
|
219
|
+
|
|
220
|
+
# Miss-vs-error: `try_` answers None for "no store has it" and
|
|
221
|
+
# RAISES for "a store could not answer" - only the miss falls
|
|
222
|
+
# through.
|
|
223
|
+
found = self._sekreto.try_(self._secretname)
|
|
224
|
+
|
|
225
|
+
if self._exchange is None:
|
|
226
|
+
if found is not None:
|
|
227
|
+
# The same live-mutation seam the test feature uses for
|
|
228
|
+
# the transport: prepare_auth reads
|
|
229
|
+
# ctx.client.options_map() (a clone of options), so the
|
|
230
|
+
# resolved value lands where the sync auth path already
|
|
231
|
+
# looks.
|
|
232
|
+
self._client.options["apikey"] = found
|
|
233
|
+
self._lastset = found
|
|
234
|
+
elif self._lastset:
|
|
235
|
+
# An UNCACHED miss after an earlier hit is a revocation:
|
|
236
|
+
# the chain now says no provider has the secret, so the
|
|
237
|
+
# value this feature wrote must not keep going out on the
|
|
238
|
+
# wire. Only the feature's own write is retracted - an
|
|
239
|
+
# explicit apikey seats FIRST in the chain as a memory
|
|
240
|
+
# provider, so the chain HITS while one is set and this
|
|
241
|
+
# branch is never reached.
|
|
242
|
+
if self._client.options.get("apikey") == self._lastset:
|
|
243
|
+
self._client.options["apikey"] = ""
|
|
244
|
+
self._lastset = None
|
|
245
|
+
return
|
|
246
|
+
|
|
247
|
+
# Exchanging: what the chain resolved is the REFRESH token, kept
|
|
248
|
+
# for every later purchase. A miss is not fatal here - an explicit
|
|
249
|
+
# `apikey` may already hold a usable access token, and the API is
|
|
250
|
+
# what gets to say whether it does.
|
|
251
|
+
self._refresh = None if found is None else str(found)
|
|
252
|
+
|
|
253
|
+
apikey = self._client.options.get("apikey")
|
|
254
|
+
if isinstance(apikey, str) and "" != apikey:
|
|
255
|
+
# A starting access token was supplied. Spend it: if it is
|
|
256
|
+
# stale the API answers 401 and the transport wrapper buys
|
|
257
|
+
# another, which is the same path expiry takes anyway.
|
|
258
|
+
return
|
|
259
|
+
|
|
260
|
+
self._client.options["apikey"] = self._buy()
|
|
261
|
+
|
|
262
|
+
# Buy an access token with the refresh token. (ts shares one in-flight
|
|
263
|
+
# purchase between concurrent async callers; python resolves
|
|
264
|
+
# synchronously, so the sharing that remains observable is the
|
|
265
|
+
# spend-what-is-current rule in _with_refresh.)
|
|
266
|
+
def _buy(self):
|
|
267
|
+
# TEST MODE BUYS NOTHING.
|
|
268
|
+
#
|
|
269
|
+
# The test feature replaces the transport so that no request
|
|
270
|
+
# leaves the process; an exchange here would be the one HTTP call
|
|
271
|
+
# it could not stop, and it would need a live token endpoint for a
|
|
272
|
+
# suite whose whole point is not needing one. So test mode gets a
|
|
273
|
+
# deterministic, obviously-fake token instead - the same answer
|
|
274
|
+
# make_options gives a required server variable, for the same
|
|
275
|
+
# reason.
|
|
276
|
+
if "live" != self._client.mode:
|
|
277
|
+
return "test-" + self._exchange["response"]
|
|
278
|
+
|
|
279
|
+
return self._buy_once()
|
|
280
|
+
|
|
281
|
+
def _buy_once(self):
|
|
282
|
+
x = self._exchange
|
|
283
|
+
|
|
284
|
+
if self._refresh is None or "" == self._refresh:
|
|
285
|
+
raise Exception(
|
|
286
|
+
"secrets: no refresh token: the provider chain has no '"
|
|
287
|
+
+ self._secretname
|
|
288
|
+
+ "', and feature.secrets.exchange.refresh is unset")
|
|
289
|
+
|
|
290
|
+
options = self._client.options_map()
|
|
291
|
+
|
|
292
|
+
# The token endpoint is RELATIVE to the base, which already
|
|
293
|
+
# carries whatever account or tenant segment the server URL
|
|
294
|
+
# declares.
|
|
295
|
+
base = str(options.get("base") or "").rstrip("/")
|
|
296
|
+
url = base + "/" + str(x["path"]).lstrip("/")
|
|
297
|
+
|
|
298
|
+
fetch = vs.getpath(options, "system.fetch")
|
|
299
|
+
|
|
300
|
+
if not callable(fetch):
|
|
301
|
+
# No custom transport supplied - the ordinary case.
|
|
302
|
+
# make_options leaves system.fetch unset, so the exchange
|
|
303
|
+
# gets its own raw HTTP path (stdlib urllib, mirroring the ts
|
|
304
|
+
# reference whose system.fetch is initialized from the
|
|
305
|
+
# platform fetcher). Local and minimal on purpose: see the
|
|
306
|
+
# NOT-the-SDK-transport note below.
|
|
307
|
+
fetch = _raw_exchange_fetch
|
|
308
|
+
|
|
309
|
+
# Deliberately NOT the SDK transport. The transport is what this
|
|
310
|
+
# feature wraps, and sending the token request back through it
|
|
311
|
+
# would recurse on the first 401 - and would route the exchange
|
|
312
|
+
# through the test mock, which knows nothing about it.
|
|
313
|
+
res, err = fetch(url, {
|
|
314
|
+
"method": x["method"],
|
|
315
|
+
"headers": {"content-type": "application/json"},
|
|
316
|
+
"body": json.dumps({x["request"]: self._refresh}),
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
if err is not None:
|
|
320
|
+
raise Exception(
|
|
321
|
+
"secrets: token exchange failed: " + str(err) + " from " + url)
|
|
322
|
+
|
|
323
|
+
status = 0 if not isinstance(res, dict) else (res.get("status") or 0)
|
|
324
|
+
|
|
325
|
+
if 200 > status or 300 <= status:
|
|
326
|
+
raise Exception(
|
|
327
|
+
"secrets: token exchange failed: " + str(status)
|
|
328
|
+
+ " from " + url)
|
|
329
|
+
|
|
330
|
+
jf = res.get("json")
|
|
331
|
+
if callable(jf):
|
|
332
|
+
body = jf()
|
|
333
|
+
else:
|
|
334
|
+
body = res.get("body")
|
|
335
|
+
if isinstance(body, str):
|
|
336
|
+
try:
|
|
337
|
+
body = json.loads(body)
|
|
338
|
+
except Exception:
|
|
339
|
+
body = None
|
|
340
|
+
|
|
341
|
+
token = None if not isinstance(body, dict) else body.get(x["response"])
|
|
342
|
+
|
|
343
|
+
if not isinstance(token, str) or "" == token:
|
|
344
|
+
raise Exception(
|
|
345
|
+
"secrets: token exchange returned no '" + x["response"]
|
|
346
|
+
+ "' field from " + url)
|
|
347
|
+
|
|
348
|
+
return token
|
|
349
|
+
|
|
350
|
+
# Buy a token and try the request again when the API says the current
|
|
351
|
+
# one is spent. Wraps the transport; installed only when exchanging.
|
|
352
|
+
#
|
|
353
|
+
# The retry rewrites the authorization header IN PLACE on the
|
|
354
|
+
# fetchdef, because the header was built by the synchronous
|
|
355
|
+
# prepare_auth before this request left, and it carries the token that
|
|
356
|
+
# just failed. Rebuilt the way prepare_auth builds it, from the same
|
|
357
|
+
# options.auth.prefix, so the two cannot drift.
|
|
358
|
+
def _with_refresh(self, ctx, url, fetchdef, inner):
|
|
359
|
+
x = self._exchange
|
|
360
|
+
max_retries = 0 if x is None else x["retries"]
|
|
361
|
+
|
|
362
|
+
# `auth: None` is the documented way to send NO credential, and
|
|
363
|
+
# prepare_auth honours it by removing the header. A refusal of a
|
|
364
|
+
# deliberately unauthenticated request is not an expired token and
|
|
365
|
+
# cannot be fixed by buying one - retrying would transmit exactly
|
|
366
|
+
# the credential the caller suppressed.
|
|
367
|
+
if self._client.options_map().get("auth") is None:
|
|
368
|
+
return inner(ctx, url, fetchdef)
|
|
369
|
+
|
|
370
|
+
attempt = 0
|
|
371
|
+
|
|
372
|
+
while True:
|
|
373
|
+
# The credential THIS attempt goes out with, captured before
|
|
374
|
+
# it leaves: it is what tells a stale refusal apart from a
|
|
375
|
+
# fresh one.
|
|
376
|
+
used = self._client.options.get("apikey")
|
|
377
|
+
|
|
378
|
+
res, err = inner(ctx, url, fetchdef)
|
|
379
|
+
|
|
380
|
+
if attempt >= max_retries or not self._spent(res, err):
|
|
381
|
+
return res, err
|
|
382
|
+
|
|
383
|
+
# Another request may have bought a token while this one was
|
|
384
|
+
# in flight. Spend what is current before buying: a second
|
|
385
|
+
# exchange for a token that is already current is wasted, and
|
|
386
|
+
# on a provider that invalidates the previous credential on
|
|
387
|
+
# issuance, one that breaks the first request's own retry.
|
|
388
|
+
current = self._client.options.get("apikey")
|
|
389
|
+
|
|
390
|
+
if isinstance(current, str) and "" != current and current != used:
|
|
391
|
+
token = current
|
|
392
|
+
else:
|
|
393
|
+
try:
|
|
394
|
+
token = self._buy()
|
|
395
|
+
except Exception:
|
|
396
|
+
# The purchase failed: answer with the API's own
|
|
397
|
+
# refusal rather than this one. The caller asked for
|
|
398
|
+
# data, and the 401 is the more useful of the two -
|
|
399
|
+
# the exchange error is a symptom.
|
|
400
|
+
return res, err
|
|
401
|
+
|
|
402
|
+
self._client.options["apikey"] = token
|
|
403
|
+
|
|
404
|
+
self._reauth(fetchdef, token)
|
|
405
|
+
|
|
406
|
+
attempt += 1
|
|
407
|
+
|
|
408
|
+
def _spent(self, res, err):
|
|
409
|
+
if err is not None or not isinstance(res, dict):
|
|
410
|
+
return False
|
|
411
|
+
return res.get("status") in self._exchange["statuses"]
|
|
412
|
+
|
|
413
|
+
def _reauth(self, fetchdef, token):
|
|
414
|
+
if not isinstance(fetchdef, dict) or \
|
|
415
|
+
not isinstance(fetchdef.get("headers"), dict):
|
|
416
|
+
return
|
|
417
|
+
|
|
418
|
+
auth = self._client.options_map().get("auth")
|
|
419
|
+
|
|
420
|
+
# Suppressed auth means NO header, the same answer prepare_auth
|
|
421
|
+
# gives. Reached defensively - _with_refresh does not retry at all
|
|
422
|
+
# when auth is None - but this is the function that writes the
|
|
423
|
+
# credential, so it is where the rule has to hold.
|
|
424
|
+
if auth is None:
|
|
425
|
+
fetchdef["headers"].pop("authorization", None)
|
|
426
|
+
return
|
|
427
|
+
|
|
428
|
+
prefix = auth.get("prefix") if isinstance(auth, dict) else None
|
|
429
|
+
fetchdef["headers"]["authorization"] = \
|
|
430
|
+
prefix + " " + token if prefix else token
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def _raw_exchange_fetch(fullurl, fetchdef):
|
|
434
|
+
"""Token-exchange transport of last resort: stdlib urllib, answering
|
|
435
|
+
the same (res, err) shape the system.fetch seam promises. Exists so an
|
|
436
|
+
exchange works with ordinary SDK options - requiring a custom
|
|
437
|
+
transport for the COMMON case would reject every live token purchase
|
|
438
|
+
before a request was made."""
|
|
439
|
+
try:
|
|
440
|
+
body = fetchdef.get("body")
|
|
441
|
+
data = body.encode("utf-8") if isinstance(body, str) and body else None
|
|
442
|
+
req = urllib.request.Request(
|
|
443
|
+
fullurl,
|
|
444
|
+
data=data,
|
|
445
|
+
method=str(fetchdef.get("method") or "POST"),
|
|
446
|
+
)
|
|
447
|
+
for k, v in (fetchdef.get("headers") or {}).items():
|
|
448
|
+
if isinstance(v, str):
|
|
449
|
+
req.add_header(k, v)
|
|
450
|
+
with urllib.request.urlopen(req, timeout=30) as res:
|
|
451
|
+
raw = res.read()
|
|
452
|
+
status = res.status
|
|
453
|
+
|
|
454
|
+
def _json():
|
|
455
|
+
try:
|
|
456
|
+
return json.loads(raw.decode("utf-8"))
|
|
457
|
+
except Exception:
|
|
458
|
+
return None
|
|
459
|
+
|
|
460
|
+
return {"status": status, "json": _json}, None
|
|
461
|
+
except urllib.error.HTTPError as e:
|
|
462
|
+
# A non-2xx answer IS a response: hand back its status so the
|
|
463
|
+
# caller reports "token exchange failed: <status>" rather than a
|
|
464
|
+
# transport error.
|
|
465
|
+
return {"status": e.code, "json": lambda: None}, None
|
|
466
|
+
except Exception as e:
|
|
467
|
+
return None, e
|
|
@@ -22,4 +22,8 @@ def prepare_method_util(ctx):
|
|
|
22
22
|
if isinstance(method, str) and "" != method:
|
|
23
23
|
return method.upper()
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
# No default: an op name outside the convention resolves to no method,
|
|
26
|
+
# exactly as the ts reference (`methodMap[key]` is undefined there).
|
|
27
|
+
# The silent-pass inline runner hid a stray "GET" fallback here; the
|
|
28
|
+
# shared corpus (prepareMethod, opname "bad" -> null) pins it now.
|
|
29
|
+
return METHOD_MAP.get(opname)
|