@voxgig/sdkgen 4.32.0 → 4.33.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/helpers/naming.js +1 -1
- package/dist/helpers/naming.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/model/sdkgen.aontu +7 -1
- package/package.json +1 -1
- package/project/.sdk/model/feature/debug.aontu +3 -1
- package/project/.sdk/src/cmp/c/PrepareAuth_c.ts +8 -28
- package/project/.sdk/src/cmp/c/TestClean_c.ts +774 -0
- package/project/.sdk/src/cmp/c/Test_c.ts +3 -0
- package/project/.sdk/src/cmp/c/fragment/Entity.fragment.c +16 -5
- package/project/.sdk/src/cmp/c/fragment/Main.fragment.c +1 -1
- package/project/.sdk/src/cmp/clojure/PrepareAuth_clojure.ts +3 -0
- package/project/.sdk/src/cmp/clojure/TestClean_clojure.ts +473 -0
- package/project/.sdk/src/cmp/clojure/Test_clojure.ts +6 -0
- package/project/.sdk/src/cmp/clojure/fragment/Entity.fragment.clj +18 -8
- package/project/.sdk/src/cmp/cpp/PrepareAuth_cpp.ts +3 -0
- package/project/.sdk/src/cmp/cpp/TestClean_cpp.ts +782 -0
- package/project/.sdk/src/cmp/cpp/TestEntity_cpp.ts +1 -1
- package/project/.sdk/src/cmp/cpp/Test_cpp.ts +2 -0
- package/project/.sdk/src/cmp/csharp/PrepareAuth_csharp.ts +3 -0
- package/project/.sdk/src/cmp/csharp/TestClean_csharp.ts +887 -0
- package/project/.sdk/src/cmp/csharp/Test_csharp.ts +2 -0
- package/project/.sdk/src/cmp/csharp/fragment/EntityBase.fragment.cs +68 -4
- package/project/.sdk/src/cmp/csharp/fragment/Main.fragment.cs +8 -2
- package/project/.sdk/src/cmp/csharp/fragment/SdkError.fragment.cs +49 -0
- package/project/.sdk/src/cmp/elixir/PrepareAuth_elixir.ts +3 -0
- package/project/.sdk/src/cmp/elixir/Schema_elixir.ts +20 -10
- package/project/.sdk/src/cmp/elixir/TestClean_elixir.ts +666 -0
- package/project/.sdk/src/cmp/elixir/Test_elixir.ts +4 -0
- package/project/.sdk/src/cmp/elixir/fragment/Main.fragment.ex +1 -1
- package/project/.sdk/src/cmp/elixir/fragment/Pipeline.fragment.ex +14 -2
- package/project/.sdk/src/cmp/go/PrepareAuth_go.ts +3 -0
- package/project/.sdk/src/cmp/go/TestClean_go.ts +804 -0
- package/project/.sdk/src/cmp/go/Test_go.ts +3 -0
- package/project/.sdk/src/cmp/go/fragment/Entity.fragment.go +54 -4
- package/project/.sdk/src/cmp/go/fragment/Main.fragment.go +27 -2
- package/project/.sdk/src/cmp/java/PrepareAuth_java.ts +3 -0
- package/project/.sdk/src/cmp/java/TestClean_java.ts +884 -0
- package/project/.sdk/src/cmp/java/Test_java.ts +2 -0
- package/project/.sdk/src/cmp/java/fragment/EntityBase.fragment.java +56 -11
- package/project/.sdk/src/cmp/java/fragment/SdkError.fragment.java +36 -3
- package/project/.sdk/src/cmp/js/PrepareAuth_js.ts +3 -0
- package/project/.sdk/src/cmp/js/TestClean_js.ts +458 -0
- package/project/.sdk/src/cmp/js/Test_js.ts +2 -0
- package/project/.sdk/src/cmp/js/fragment/EntityBase.fragment.js +5 -4
- package/project/.sdk/src/cmp/js/fragment/EntityCreateOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/EntityListOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/EntityLoadOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/EntityRemoveOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/EntityUpdateOp.fragment.js +7 -1
- package/project/.sdk/src/cmp/js/fragment/Main.fragment.js +11 -2
- package/project/.sdk/src/cmp/js/fragment/SdkError.fragment.js +17 -1
- package/project/.sdk/src/cmp/kotlin/Package_kotlin.ts +5 -0
- package/project/.sdk/src/cmp/kotlin/PrepareAuth_kotlin.ts +3 -0
- package/project/.sdk/src/cmp/kotlin/TestClean_kotlin.ts +654 -0
- package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +3 -0
- package/project/.sdk/src/cmp/kotlin/fragment/EntityBase.fragment.kt +44 -11
- package/project/.sdk/src/cmp/kotlin/fragment/SdkError.fragment.kt +31 -0
- package/project/.sdk/src/cmp/lua/PrepareAuth_lua.ts +3 -0
- package/project/.sdk/src/cmp/lua/TestClean_lua.ts +769 -0
- package/project/.sdk/src/cmp/lua/Test_lua.ts +3 -0
- package/project/.sdk/src/cmp/lua/fragment/Entity.fragment.lua +77 -1
- package/project/.sdk/src/cmp/lua/fragment/Main.fragment.lua +49 -2
- package/project/.sdk/src/cmp/ocaml/Entity_ocaml.ts +3 -2
- package/project/.sdk/src/cmp/ocaml/PrepareAuth_ocaml.ts +4 -25
- package/project/.sdk/src/cmp/ocaml/TestClean_ocaml.ts +538 -0
- package/project/.sdk/src/cmp/ocaml/Test_ocaml.ts +5 -0
- package/project/.sdk/src/cmp/ocaml/fragment/RunOp.fragment.ml +16 -4
- package/project/.sdk/src/cmp/perl/PrepareAuth_perl.ts +3 -0
- package/project/.sdk/src/cmp/perl/TestClean_perl.ts +619 -0
- package/project/.sdk/src/cmp/perl/Test_perl.ts +3 -0
- package/project/.sdk/src/cmp/perl/fragment/Entity.fragment.pm +67 -5
- package/project/.sdk/src/cmp/perl/fragment/Main.fragment.pm +13 -1
- package/project/.sdk/src/cmp/php/PrepareAuth_php.ts +3 -0
- package/project/.sdk/src/cmp/php/TestClean_php.ts +809 -0
- package/project/.sdk/src/cmp/php/Test_php.ts +2 -0
- package/project/.sdk/src/cmp/php/fragment/Entity.fragment.php +96 -55
- package/project/.sdk/src/cmp/php/fragment/Main.fragment.php +15 -2
- package/project/.sdk/src/cmp/py/PrepareAuth_py.ts +3 -0
- package/project/.sdk/src/cmp/py/TestClean_py.ts +549 -0
- package/project/.sdk/src/cmp/py/Test_py.ts +3 -0
- package/project/.sdk/src/cmp/py/fragment/Entity.fragment.py +83 -55
- package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +19 -3
- package/project/.sdk/src/cmp/rb/PrepareAuth_rb.ts +3 -0
- package/project/.sdk/src/cmp/rb/TestClean_rb.ts +535 -0
- package/project/.sdk/src/cmp/rb/Test_rb.ts +3 -0
- package/project/.sdk/src/cmp/rb/fragment/Entity.fragment.rb +108 -46
- package/project/.sdk/src/cmp/rb/fragment/Main.fragment.rb +12 -1
- package/project/.sdk/src/cmp/rust/PrepareAuth_rust.ts +9 -45
- package/project/.sdk/src/cmp/rust/TestClean_rust.ts +881 -0
- package/project/.sdk/src/cmp/rust/Test_rust.ts +3 -0
- package/project/.sdk/src/cmp/rust/fragment/Entity.fragment.rs +14 -6
- package/project/.sdk/src/cmp/rust/fragment/Main.fragment.rs +17 -1
- package/project/.sdk/src/cmp/rust/fragment/SdkError.fragment.rs +34 -2
- package/project/.sdk/src/cmp/scala/PrepareAuth_scala.ts +3 -0
- package/project/.sdk/src/cmp/scala/TestClean_scala.ts +608 -0
- package/project/.sdk/src/cmp/scala/Test_scala.ts +3 -0
- package/project/.sdk/src/cmp/scala/fragment/EntityBase.fragment.scala +58 -6
- package/project/.sdk/src/cmp/swift/PrepareAuth_swift.ts +3 -0
- package/project/.sdk/src/cmp/swift/TestClean_swift.ts +671 -0
- package/project/.sdk/src/cmp/swift/Test_swift.ts +3 -0
- package/project/.sdk/src/cmp/swift/fragment/EntityBase.fragment.swift +10 -0
- package/project/.sdk/src/cmp/swift/fragment/Main.fragment.swift +16 -2
- package/project/.sdk/src/cmp/swift/fragment/SdkError.fragment.swift +47 -3
- package/project/.sdk/src/cmp/ts/PrepareAuth_ts.ts +3 -0
- package/project/.sdk/src/cmp/ts/TestClean_ts.ts +465 -0
- package/project/.sdk/src/cmp/ts/Test_ts.ts +2 -0
- package/project/.sdk/src/cmp/ts/fragment/EntityBase.fragment.ts +5 -4
- package/project/.sdk/src/cmp/ts/fragment/EntityCreateOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityListOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityLoadOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityRemoveOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/EntityUpdateOp.fragment.ts +7 -1
- package/project/.sdk/src/cmp/ts/fragment/Main.fragment.ts +8 -2
- package/project/.sdk/src/cmp/ts/fragment/SdkError.fragment.ts +20 -2
- package/project/.sdk/src/cmp/zig/PrepareAuth_zig.ts +3 -0
- package/project/.sdk/src/cmp/zig/TestClean_zig.ts +791 -0
- package/project/.sdk/src/cmp/zig/Test_zig.ts +5 -0
- package/project/.sdk/src/cmp/zig/fragment/Build.fragment.zig +19 -0
- package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +14 -5
- package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +1 -1
- package/project/.sdk/tm/c/core/context.c +25 -0
- package/project/.sdk/tm/c/core/error.c +16 -0
- package/project/.sdk/tm/c/core/sdk.h +22 -0
- package/project/.sdk/tm/c/feature/audit.c +2 -0
- package/project/.sdk/tm/c/feature/cost.c +1 -0
- package/project/.sdk/tm/c/feature/debug.c +19 -29
- package/project/.sdk/tm/c/feature/log.c +21 -2
- package/project/.sdk/tm/c/feature/proxy.c +55 -3
- package/project/.sdk/tm/c/feature/secrets.c +7 -0
- package/project/.sdk/tm/c/feature/telemetry.c +2 -0
- package/project/.sdk/tm/c/tests/feature_test.c +2 -2
- package/project/.sdk/tm/c/utility/clean.c +530 -8
- package/project/.sdk/tm/c/utility/done.c +28 -12
- package/project/.sdk/tm/c/utility/make_error.c +4 -3
- package/project/.sdk/tm/c/utility/make_options.c +71 -45
- package/project/.sdk/tm/clojure/feature/secrets/sdk/feature/secrets.clj +15 -0
- package/project/.sdk/tm/clojure/src/sdk/client.clj +20 -4
- package/project/.sdk/tm/clojure/src/sdk/core.clj +319 -35
- package/project/.sdk/tm/clojure/src/sdk/features.clj +68 -30
- package/project/.sdk/tm/clojure/test/sdk/test/feature.clj +4 -2
- package/project/.sdk/tm/clojure/test/sdk/test/pipeline.clj +47 -20
- package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +4 -0
- package/project/.sdk/tm/cpp/core/types.hpp +93 -3
- package/project/.sdk/tm/cpp/feature/audit.hpp +1 -0
- package/project/.sdk/tm/cpp/feature/cost.hpp +1 -0
- package/project/.sdk/tm/cpp/feature/debug.hpp +20 -12
- package/project/.sdk/tm/cpp/feature/log.hpp +31 -9
- package/project/.sdk/tm/cpp/feature/proxy.hpp +52 -6
- package/project/.sdk/tm/cpp/feature/secrets.hpp +13 -0
- package/project/.sdk/tm/cpp/feature/telemetry.hpp +4 -2
- package/project/.sdk/tm/cpp/test/feature_test.cpp +2 -2
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +426 -51
- package/project/.sdk/tm/csharp/core/Context.cs +32 -0
- package/project/.sdk/tm/csharp/core/Utility.cs +2 -0
- package/project/.sdk/tm/csharp/feature/AuditFeature.cs +1 -0
- package/project/.sdk/tm/csharp/feature/CostFeature.cs +7 -5
- package/project/.sdk/tm/csharp/feature/DebugFeature.cs +19 -16
- package/project/.sdk/tm/csharp/feature/FeatureOptions.cs +16 -0
- package/project/.sdk/tm/csharp/feature/LogFeature.cs +4 -1
- package/project/.sdk/tm/csharp/feature/ProxyFeature.cs +26 -5
- package/project/.sdk/tm/csharp/feature/SecretsFeature.cs +16 -0
- package/project/.sdk/tm/csharp/feature/TelemetryFeature.cs +4 -2
- package/project/.sdk/tm/csharp/test/FeatureTest.cs +2 -2
- package/project/.sdk/tm/csharp/utility/Clean.cs +440 -2
- package/project/.sdk/tm/csharp/utility/Done.cs +27 -11
- package/project/.sdk/tm/csharp/utility/MakeError.cs +19 -8
- package/project/.sdk/tm/csharp/utility/MakeOptions.cs +119 -29
- package/project/.sdk/tm/csharp/utility/MakeResponse.cs +21 -11
- package/project/.sdk/tm/csharp/utility/Register.cs +1 -0
- package/project/.sdk/tm/elixir/lib/projectname/context.ex +19 -0
- package/project/.sdk/tm/elixir/lib/projectname/entity_base.ex +22 -1
- package/project/.sdk/tm/elixir/lib/projectname/error.ex +24 -0
- package/project/.sdk/tm/elixir/lib/projectname/feature/audit.ex +2 -2
- package/project/.sdk/tm/elixir/lib/projectname/feature/cost.ex +2 -2
- package/project/.sdk/tm/elixir/lib/projectname/feature/debug.ex +13 -13
- package/project/.sdk/tm/elixir/lib/projectname/feature/log.ex +18 -5
- package/project/.sdk/tm/elixir/lib/projectname/feature/proxy.ex +19 -1
- package/project/.sdk/tm/elixir/lib/projectname/feature/secrets.ex +15 -0
- package/project/.sdk/tm/elixir/lib/projectname/feature/telemetry.ex +4 -2
- package/project/.sdk/tm/elixir/lib/projectname/feature.ex +22 -0
- package/project/.sdk/tm/elixir/lib/projectname/utility.ex +464 -41
- package/project/.sdk/tm/elixir/test/feature_test.exs +3 -2
- package/project/.sdk/tm/go/core/context.go +42 -0
- package/project/.sdk/tm/go/core/error.go +30 -10
- package/project/.sdk/tm/go/core/utility_type.go +2 -0
- package/project/.sdk/tm/go/feature/audit_feature.go +1 -0
- package/project/.sdk/tm/go/feature/base_feature.go +12 -0
- package/project/.sdk/tm/go/feature/cost_feature.go +2 -2
- package/project/.sdk/tm/go/feature/debug_feature.go +14 -12
- package/project/.sdk/tm/go/feature/log_feature.go +13 -8
- package/project/.sdk/tm/go/feature/proxy_feature.go +26 -6
- package/project/.sdk/tm/go/feature/secrets_feature.go +19 -0
- package/project/.sdk/tm/go/feature/telemetry_feature.go +4 -2
- package/project/.sdk/tm/go/test/feature_test.go +2 -2
- package/project/.sdk/tm/go/utility/clean.go +585 -2
- package/project/.sdk/tm/go/utility/done.go +29 -9
- package/project/.sdk/tm/go/utility/make_error.go +51 -16
- package/project/.sdk/tm/go/utility/make_options.go +77 -36
- package/project/.sdk/tm/go/utility/register.go +12 -0
- package/project/.sdk/tm/java/core/Context.java +29 -0
- package/project/.sdk/tm/java/core/SdkClient.java +4 -2
- package/project/.sdk/tm/java/core/Utility.java +7 -0
- package/project/.sdk/tm/java/feature/AuditFeature.java +6 -0
- package/project/.sdk/tm/java/feature/CostFeature.java +5 -0
- package/project/.sdk/tm/java/feature/DebugFeature.java +25 -14
- package/project/.sdk/tm/java/feature/LogFeature.java +11 -4
- package/project/.sdk/tm/java/feature/ProxyFeature.java +41 -6
- package/project/.sdk/tm/java/feature/SecretsFeature.java +18 -0
- package/project/.sdk/tm/java/feature/TelemetryFeature.java +8 -2
- package/project/.sdk/tm/java/test/FeatureTest.java +2 -2
- package/project/.sdk/tm/java/utility/Clean.java +519 -1
- package/project/.sdk/tm/java/utility/Done.java +1 -1
- package/project/.sdk/tm/java/utility/MakeError.java +5 -1
- package/project/.sdk/tm/java/utility/MakeOptions.java +55 -31
- package/project/.sdk/tm/java/utility/Register.java +4 -0
- package/project/.sdk/tm/js/src/Context.js +5 -1
- package/project/.sdk/tm/js/src/Response.js +14 -1
- package/project/.sdk/tm/js/src/feature/audit/AuditFeature.js +2 -2
- package/project/.sdk/tm/js/src/feature/cost/CostFeature.js +2 -2
- package/project/.sdk/tm/js/src/feature/debug/DebugFeature.js +13 -7
- package/project/.sdk/tm/js/src/feature/log/LogFeature.js +9 -5
- package/project/.sdk/tm/js/src/feature/proxy/ProxyFeature.js +19 -1
- package/project/.sdk/tm/js/src/feature/secrets/SecretsFeature.js +14 -0
- package/project/.sdk/tm/js/src/feature/telemetry/TelemetryFeature.js +4 -2
- package/project/.sdk/tm/js/src/utility/CleanUtility.js +294 -21
- package/project/.sdk/tm/js/src/utility/DoneUtility.js +17 -5
- package/project/.sdk/tm/js/src/utility/MakeErrorUtility.js +18 -2
- package/project/.sdk/tm/js/src/utility/MakeOptionsUtility.js +39 -15
- package/project/.sdk/tm/js/src/utility/Utility.js +4 -2
- package/project/.sdk/tm/js/test/feature/harness.js +11 -1
- package/project/.sdk/tm/js/test/feature.test.js +9 -2
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +25 -0
- package/project/.sdk/tm/kotlin/core/Context.kt +19 -0
- package/project/.sdk/tm/kotlin/core/SdkClient.kt +9 -2
- package/project/.sdk/tm/kotlin/core/Utility.kt +2 -0
- package/project/.sdk/tm/kotlin/feature/AuditFeature.kt +11 -9
- package/project/.sdk/tm/kotlin/feature/CostFeature.kt +8 -5
- package/project/.sdk/tm/kotlin/feature/DebugFeature.kt +15 -22
- package/project/.sdk/tm/kotlin/feature/LogFeature.kt +8 -4
- package/project/.sdk/tm/kotlin/feature/ProxyFeature.kt +26 -2
- package/project/.sdk/tm/kotlin/feature/SecretsFeature.kt +11 -0
- package/project/.sdk/tm/kotlin/feature/TelemetryFeature.kt +4 -2
- package/project/.sdk/tm/kotlin/test/FeatureTest.kt +2 -2
- package/project/.sdk/tm/kotlin/utility/CoreUtil.kt +447 -11
- package/project/.sdk/tm/kotlin/utility/MakeOptions.kt +38 -31
- package/project/.sdk/tm/kotlin/utility/Register.kt +1 -0
- package/project/.sdk/tm/lua/core/context.lua +43 -0
- package/project/.sdk/tm/lua/core/error.lua +36 -1
- package/project/.sdk/tm/lua/core/utility_type.lua +4 -0
- package/project/.sdk/tm/lua/feature/audit_feature.lua +2 -2
- package/project/.sdk/tm/lua/feature/cost_feature.lua +2 -2
- package/project/.sdk/tm/lua/feature/debug_feature.lua +21 -17
- package/project/.sdk/tm/lua/feature/log_feature.lua +2 -1
- package/project/.sdk/tm/lua/feature/proxy_feature.lua +23 -1
- package/project/.sdk/tm/lua/feature/secrets_feature.lua +18 -0
- package/project/.sdk/tm/lua/feature/telemetry_feature.lua +4 -2
- package/project/.sdk/tm/lua/test/feature/secrets/secrets_feature_test.lua +3 -2
- package/project/.sdk/tm/lua/test/feature_test.lua +10 -3
- package/project/.sdk/tm/lua/utility/clean.lua +426 -2
- package/project/.sdk/tm/lua/utility/clean_explain.lua +34 -0
- package/project/.sdk/tm/lua/utility/done.lua +1 -7
- package/project/.sdk/tm/lua/utility/make_error.lua +3 -1
- package/project/.sdk/tm/lua/utility/make_options.lua +76 -30
- package/project/.sdk/tm/lua/utility/register.lua +4 -1
- package/project/.sdk/tm/ocaml/Makefile +5 -1
- package/project/.sdk/tm/ocaml/feature/secrets_feature.ml +12 -1
- package/project/.sdk/tm/ocaml/sdk_features.ml +78 -18
- package/project/.sdk/tm/ocaml/sdk_helpers.ml +27 -0
- package/project/.sdk/tm/ocaml/sdk_runtime.ml +304 -26
- package/project/.sdk/tm/ocaml/sdk_types.ml +1 -0
- package/project/.sdk/tm/ocaml/test/feature/secrets/t_secrets.ml +3 -1
- package/project/.sdk/tm/ocaml/test/t_feature.ml +2 -2
- package/project/.sdk/tm/perl/core/context.pm +27 -0
- package/project/.sdk/tm/perl/core/error.pm +52 -5
- package/project/.sdk/tm/perl/feature/audit_feature.pm +2 -2
- package/project/.sdk/tm/perl/feature/cost_feature.pm +2 -2
- package/project/.sdk/tm/perl/feature/debug_feature.pm +17 -13
- package/project/.sdk/tm/perl/feature/log_feature.pm +3 -1
- package/project/.sdk/tm/perl/feature/proxy_feature.pm +21 -1
- package/project/.sdk/tm/perl/feature/secrets_feature.pm +20 -1
- package/project/.sdk/tm/perl/feature/telemetry_feature.pm +4 -2
- package/project/.sdk/tm/perl/t/feature.t +4 -2
- package/project/.sdk/tm/perl/utility/clean.pm +345 -1
- package/project/.sdk/tm/perl/utility/done.pm +24 -6
- package/project/.sdk/tm/perl/utility/make_error.pm +17 -4
- package/project/.sdk/tm/perl/utility/make_options.pm +33 -14
- package/project/.sdk/tm/php/core/Context.php +24 -1
- package/project/.sdk/tm/php/core/Error.php +34 -3
- package/project/.sdk/tm/php/core/UtilityType.php +4 -0
- package/project/.sdk/tm/php/feature/AuditFeature.php +2 -2
- package/project/.sdk/tm/php/feature/CostFeature.php +2 -2
- package/project/.sdk/tm/php/feature/DebugFeature.php +18 -9
- package/project/.sdk/tm/php/feature/LogFeature.php +5 -2
- package/project/.sdk/tm/php/feature/ProxyFeature.php +20 -1
- package/project/.sdk/tm/php/feature/SecretsFeature.php +18 -0
- package/project/.sdk/tm/php/feature/TelemetryFeature.php +4 -2
- package/project/.sdk/tm/php/test/FeatureTest.php +2 -2
- package/project/.sdk/tm/php/utility/Clean.php +438 -2
- package/project/.sdk/tm/php/utility/Done.php +14 -7
- package/project/.sdk/tm/php/utility/MakeError.php +9 -7
- package/project/.sdk/tm/php/utility/MakeOptions.php +62 -38
- package/project/.sdk/tm/php/utility/Register.php +2 -0
- package/project/.sdk/tm/py/pkg/core/context.py +17 -0
- package/project/.sdk/tm/py/pkg/core/error.py +42 -1
- package/project/.sdk/tm/py/pkg/core/utility_type.py +4 -0
- package/project/.sdk/tm/py/pkg/feature/audit_feature.py +2 -2
- package/project/.sdk/tm/py/pkg/feature/cost_feature.py +2 -2
- package/project/.sdk/tm/py/pkg/feature/debug_feature.py +17 -12
- package/project/.sdk/tm/py/pkg/feature/log_feature.py +2 -1
- package/project/.sdk/tm/py/pkg/feature/proxy_feature.py +18 -1
- package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +12 -0
- package/project/.sdk/tm/py/pkg/feature/telemetry_feature.py +4 -2
- package/project/.sdk/tm/py/pkg/utility/clean.py +311 -1
- package/project/.sdk/tm/py/pkg/utility/done.py +18 -5
- package/project/.sdk/tm/py/pkg/utility/make_error.py +9 -6
- package/project/.sdk/tm/py/pkg/utility/make_options.py +64 -25
- package/project/.sdk/tm/py/pkg/utility/make_response.py +19 -13
- package/project/.sdk/tm/py/pkg/utility/register.py +4 -2
- package/project/.sdk/tm/py/test/feature_harness.py +4 -0
- package/project/.sdk/tm/py/test/test_feature.py +2 -2
- package/project/.sdk/tm/py/test/test_primary_utility.py +1 -0
- package/project/.sdk/tm/rb/core/context.rb +28 -0
- package/project/.sdk/tm/rb/core/error.rb +30 -0
- package/project/.sdk/tm/rb/core/utility_type.rb +1 -1
- package/project/.sdk/tm/rb/feature/audit_feature.rb +2 -2
- package/project/.sdk/tm/rb/feature/cost_feature.rb +2 -2
- package/project/.sdk/tm/rb/feature/debug_feature.rb +15 -12
- package/project/.sdk/tm/rb/feature/log_feature.rb +3 -1
- package/project/.sdk/tm/rb/feature/proxy_feature.rb +25 -1
- package/project/.sdk/tm/rb/feature/secrets_feature.rb +17 -0
- package/project/.sdk/tm/rb/feature/telemetry_feature.rb +4 -2
- package/project/.sdk/tm/rb/test/feature_test.rb +4 -2
- package/project/.sdk/tm/rb/utility/clean.rb +312 -1
- package/project/.sdk/tm/rb/utility/done.rb +15 -5
- package/project/.sdk/tm/rb/utility/make_error.rb +13 -4
- package/project/.sdk/tm/rb/utility/make_options.rb +31 -12
- package/project/.sdk/tm/rb/utility/register.rb +2 -0
- package/project/.sdk/tm/rust/core/context.rs +55 -0
- package/project/.sdk/tm/rust/core/utility_type.rs +17 -0
- package/project/.sdk/tm/rust/feature/audit.rs +2 -0
- package/project/.sdk/tm/rust/feature/cost.rs +3 -2
- package/project/.sdk/tm/rust/feature/debug.rs +16 -16
- package/project/.sdk/tm/rust/feature/log.rs +42 -7
- package/project/.sdk/tm/rust/feature/proxy.rs +48 -2
- package/project/.sdk/tm/rust/feature/secrets.rs +12 -0
- package/project/.sdk/tm/rust/feature/telemetry.rs +2 -0
- package/project/.sdk/tm/rust/tests/feature_test.rs +2 -2
- package/project/.sdk/tm/rust/utility/clean.rs +446 -5
- package/project/.sdk/tm/rust/utility/done.rs +22 -12
- package/project/.sdk/tm/rust/utility/make_error.rs +4 -1
- package/project/.sdk/tm/rust/utility/make_options.rs +73 -19
- package/project/.sdk/tm/scala/Makefile +3 -1
- package/project/.sdk/tm/scala/core/Context.scala +16 -0
- package/project/.sdk/tm/scala/core/SdkClient.scala +14 -4
- package/project/.sdk/tm/scala/core/SdkError.scala +28 -0
- package/project/.sdk/tm/scala/core/Types.scala +3 -0
- package/project/.sdk/tm/scala/core/Utility.scala +2 -0
- package/project/.sdk/tm/scala/feature/AuditFeature.scala +16 -10
- package/project/.sdk/tm/scala/feature/CostFeature.scala +10 -5
- package/project/.sdk/tm/scala/feature/DebugFeature.scala +24 -21
- package/project/.sdk/tm/scala/feature/LogFeature.scala +9 -4
- package/project/.sdk/tm/scala/feature/ProxyFeature.scala +23 -2
- package/project/.sdk/tm/scala/feature/SecretsFeature.scala +14 -0
- package/project/.sdk/tm/scala/feature/TelemetryFeature.scala +9 -2
- package/project/.sdk/tm/scala/sdktest/SdkTestMain.scala +2 -2
- package/project/.sdk/tm/scala/utility/Make.scala +63 -20
- package/project/.sdk/tm/scala/utility/Misc.scala +358 -5
- package/project/.sdk/tm/scala/utility/Register.scala +1 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Context.swift +29 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/core/Utility.swift +2 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/AuditFeature.swift +10 -9
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/CostFeature.swift +7 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/DebugFeature.swift +19 -15
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/FeatureOptions.swift +16 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/LogFeature.swift +4 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/ProxyFeature.swift +20 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/SecretsFeature.swift +13 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/feature/TelemetryFeature.swift +4 -2
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeError.swift +15 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/MakeOptions.swift +58 -19
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Register.swift +1 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/ResultUtil.swift +391 -4
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/FeatureTest.swift +2 -2
- package/project/.sdk/tm/ts/src/Context.ts +5 -1
- package/project/.sdk/tm/ts/src/Response.ts +14 -1
- package/project/.sdk/tm/ts/src/feature/audit/AuditFeature.ts +2 -2
- package/project/.sdk/tm/ts/src/feature/cost/CostFeature.ts +2 -2
- package/project/.sdk/tm/ts/src/feature/debug/DebugFeature.ts +13 -7
- package/project/.sdk/tm/ts/src/feature/log/LogFeature.ts +9 -5
- package/project/.sdk/tm/ts/src/feature/proxy/ProxyFeature.ts +19 -1
- package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +12 -0
- package/project/.sdk/tm/ts/src/feature/telemetry/TelemetryFeature.ts +4 -2
- package/project/.sdk/tm/ts/src/utility/CleanUtility.ts +287 -9
- package/project/.sdk/tm/ts/src/utility/DoneUtility.ts +18 -5
- package/project/.sdk/tm/ts/src/utility/MakeErrorUtility.ts +18 -8
- package/project/.sdk/tm/ts/src/utility/MakeOptionsUtility.ts +38 -16
- package/project/.sdk/tm/ts/src/utility/Utility.ts +4 -2
- package/project/.sdk/tm/ts/test/feature/harness.ts +11 -1
- package/project/.sdk/tm/ts/test/feature.test.ts +9 -2
- package/project/.sdk/tm/ts/test/utility/PrimaryUtility.test.ts +25 -0
- package/project/.sdk/tm/zig/core/context.zig +34 -0
- package/project/.sdk/tm/zig/core/error.zig +22 -1
- package/project/.sdk/tm/zig/core/utility.zig +403 -39
- package/project/.sdk/tm/zig/feature/audit.zig +4 -2
- package/project/.sdk/tm/zig/feature/cost.zig +3 -2
- package/project/.sdk/tm/zig/feature/debug.zig +20 -25
- package/project/.sdk/tm/zig/feature/log.zig +3 -1
- package/project/.sdk/tm/zig/feature/proxy.zig +47 -6
- package/project/.sdk/tm/zig/feature/secrets.zig +7 -0
- package/project/.sdk/tm/zig/feature/telemetry.zig +4 -2
- package/project/.sdk/tm/zig/test/feature_test.zig +2 -2
- package/project/sdkgen-package.json +1 -1
- package/src/helpers/naming.ts +1 -1
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cmp,
|
|
3
|
+
File,
|
|
4
|
+
Content,
|
|
5
|
+
isAuthSuppressed,
|
|
6
|
+
isHttpBasicAuth,
|
|
7
|
+
resolveAuthIn,
|
|
8
|
+
resolveAuthName,
|
|
9
|
+
} from '@voxgig/sdkgen'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
// The canary sweep: every credential slot holds a distinctive value, every
|
|
13
|
+
// diagnostic feature this SDK ships is switched on with a capturing sink, a
|
|
14
|
+
// real operation runs through every outcome, and every string that leaves
|
|
15
|
+
// the SDK is searched for the canaries and their encoded forms. It also
|
|
16
|
+
// proves its own sensitivity: with clean switched off the canary MUST show.
|
|
17
|
+
const TestClean = cmp(function TestClean(props: any) {
|
|
18
|
+
const { model } = props.ctx$
|
|
19
|
+
const { target } = props
|
|
20
|
+
|
|
21
|
+
const auth = {
|
|
22
|
+
suppressed: isAuthSuppressed(model),
|
|
23
|
+
where: resolveAuthIn(model),
|
|
24
|
+
name: 'header' === resolveAuthIn(model)
|
|
25
|
+
? resolveAuthName(model).toLowerCase() : resolveAuthName(model),
|
|
26
|
+
basic: isHttpBasicAuth(model),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
File({ name: 'test_clean.' + target.ext }, () => Content(render(model.const.Name, auth)))
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
function render(Name: string, auth: {
|
|
34
|
+
suppressed: boolean, where: string, name: string, basic: boolean
|
|
35
|
+
}): string {
|
|
36
|
+
const pkg = Name.toLowerCase() + '_sdk'
|
|
37
|
+
|
|
38
|
+
return `# ${Name} SDK clean test
|
|
39
|
+
#
|
|
40
|
+
# The canary sweep: no credential leaves the SDK in any form.
|
|
41
|
+
|
|
42
|
+
import base64
|
|
43
|
+
import json
|
|
44
|
+
import traceback
|
|
45
|
+
from urllib.parse import quote
|
|
46
|
+
|
|
47
|
+
import pytest
|
|
48
|
+
|
|
49
|
+
from ${pkg} import ${Name}SDK
|
|
50
|
+
from ${pkg}.core.error import ${Name}Error
|
|
51
|
+
from ${pkg}.feature.base_feature import ${Name}BaseFeature
|
|
52
|
+
from test.feature_harness import has_feature
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# Generated: the credential's wire placement is fixed when the SDK is built.
|
|
56
|
+
AUTH = ${JSON.stringify(auth)
|
|
57
|
+
.replace(/true/g, 'True').replace(/false/g, 'False')}
|
|
58
|
+
|
|
59
|
+
CANARY = {
|
|
60
|
+
"apikey": "CANARY-APIKEY-k9x2m7q4p1",
|
|
61
|
+
"secret": "CANARY-SECRET-w3e8r5t2y6",
|
|
62
|
+
"header": "CANARY-HEADER-z1x4c7v0b3",
|
|
63
|
+
"value": "CANARY-VALUE-n5m8b2v9c4",
|
|
64
|
+
"config": "CANARY-CONFIG-h6j3k8l2m5",
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
MASK = "[redacted]"
|
|
68
|
+
|
|
69
|
+
NO_OP = "no operation of this SDK completes against a plain 200; nothing to sweep"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _b64(s):
|
|
73
|
+
return base64.b64encode(s.encode("utf-8")).decode("ascii")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Every form a canary can travel in.
|
|
77
|
+
FORMS = []
|
|
78
|
+
for _v in CANARY.values():
|
|
79
|
+
FORMS.extend([_v, _b64(_v), quote(_v, safe="")])
|
|
80
|
+
FORMS.append(_b64(CANARY["apikey"] + ":" + CANARY["secret"]))
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# Header maps keep the caller's spelling; the assertion should not care.
|
|
84
|
+
def _header(m, name):
|
|
85
|
+
for k in (m or {}):
|
|
86
|
+
if str(k).lower() == name.lower():
|
|
87
|
+
return m[k]
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _leaks(text):
|
|
92
|
+
return [f for f in FORMS if f in text]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _plain(v):
|
|
96
|
+
return v if isinstance(v, dict) or v is None else vars(v)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# Every default print of a value: json, str and repr, plus what an
|
|
100
|
+
# exception shows a traceback and an attribute dump.
|
|
101
|
+
def _forms(name, val):
|
|
102
|
+
out = []
|
|
103
|
+
|
|
104
|
+
def push(kind, fn):
|
|
105
|
+
try:
|
|
106
|
+
out.append((name + ":" + kind, fn()))
|
|
107
|
+
except Exception:
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
push("json", lambda: json.dumps(val, default=str))
|
|
111
|
+
push("str", lambda: str(val))
|
|
112
|
+
push("repr", lambda: repr(val))
|
|
113
|
+
if isinstance(val, BaseException):
|
|
114
|
+
push("message", lambda: str(val.args))
|
|
115
|
+
push("traceback", lambda: "".join(traceback.format_exception(val)))
|
|
116
|
+
push("vars", lambda: json.dumps(vars(val), default=str))
|
|
117
|
+
push("spec", lambda: json.dumps(_plain(getattr(val, "spec", None)), default=str))
|
|
118
|
+
push("result", lambda: json.dumps(_plain(getattr(val, "result", None)), default=str))
|
|
119
|
+
if callable(getattr(val, "to_json", None)):
|
|
120
|
+
push("to_json", lambda: json.dumps(val.to_json(), default=str))
|
|
121
|
+
if callable(getattr(val, "data_get", None)):
|
|
122
|
+
push("data", lambda: json.dumps(val.data_get(), default=str))
|
|
123
|
+
return out
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# Captures the serialised context from inside the pipeline: what a hook
|
|
127
|
+
# author would hand to a logger.
|
|
128
|
+
class _CaptureFeature(${Name}BaseFeature):
|
|
129
|
+
def __init__(self, sinks):
|
|
130
|
+
super().__init__()
|
|
131
|
+
self.name = "capture"
|
|
132
|
+
self.version = "0.0.1"
|
|
133
|
+
self.active = True
|
|
134
|
+
self._sinks = sinks
|
|
135
|
+
|
|
136
|
+
def init(self, ctx, options):
|
|
137
|
+
pass
|
|
138
|
+
|
|
139
|
+
def PreRequest(self, ctx):
|
|
140
|
+
self._sinks.extend(_forms("ctx@PreRequest", ctx))
|
|
141
|
+
|
|
142
|
+
def PreResponse(self, ctx):
|
|
143
|
+
self._sinks.extend(_forms("ctx@PreResponse", ctx))
|
|
144
|
+
|
|
145
|
+
# The SDK's own error as a hook reads it, which an observability
|
|
146
|
+
# feature logs.
|
|
147
|
+
def PreUnexpected(self, ctx):
|
|
148
|
+
self._sinks.extend(_forms("ctx@PreUnexpected", ctx))
|
|
149
|
+
if isinstance(ctx.ctrl.err, ${Name}Error):
|
|
150
|
+
self._sinks.extend(_forms("ctrl.err@PreUnexpected", ctx.ctrl.err))
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _response(status, data, headers=None):
|
|
154
|
+
h = {"content-type": "application/json"}
|
|
155
|
+
h.update(headers or {})
|
|
156
|
+
return {
|
|
157
|
+
"status": status,
|
|
158
|
+
"statusText": "OK" if status < 400 else "ERR",
|
|
159
|
+
"headers": h,
|
|
160
|
+
"json": lambda: data,
|
|
161
|
+
"body": json.dumps(data),
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _notjson():
|
|
166
|
+
def raise_json():
|
|
167
|
+
raise ValueError("Unexpected token < in JSON")
|
|
168
|
+
return {
|
|
169
|
+
"status": 200,
|
|
170
|
+
"statusText": "OK",
|
|
171
|
+
"headers": {},
|
|
172
|
+
"json": raise_json,
|
|
173
|
+
"body": "<html>",
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
# The transport answers a (response, error) pair; a transport error is the
|
|
178
|
+
# pair with the error set, and its message quotes the URL.
|
|
179
|
+
SCENARIOS = [
|
|
180
|
+
("ok", lambda url, fetchdef: (_response(200, {"id": "i1", "name": "n1"},
|
|
181
|
+
{"x-session-token": "RESP-TOKEN-a1b2c3d4e5"}), None)),
|
|
182
|
+
("notfound", lambda url, fetchdef: (_response(404, {"error": "no such record"}), None)),
|
|
183
|
+
("server", lambda url, fetchdef: (_response(500, {"error": "boom"}), None)),
|
|
184
|
+
("transport", lambda url, fetchdef: (None, RuntimeError('socket hang up (URL was: "' + url + '")'))),
|
|
185
|
+
# The SDK's own error, its code quoting a registered value.
|
|
186
|
+
("coded", lambda url, fetchdef: (None, ${Name}Error("denied_" + CANARY["apikey"], "coded failure"))),
|
|
187
|
+
("notjson", lambda url, fetchdef: (_notjson(), None)),
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _make_sdk(respond, sinks, cleanopts=None, extra=None):
|
|
192
|
+
def capture(name):
|
|
193
|
+
return lambda rec, *a: sinks.extend(_forms(name, rec))
|
|
194
|
+
|
|
195
|
+
feature = {}
|
|
196
|
+
if has_feature("log"):
|
|
197
|
+
logger = {}
|
|
198
|
+
for level in ["trace", "debug", "info", "warn", "error", "fatal"]:
|
|
199
|
+
logger[level] = capture("log." + level)
|
|
200
|
+
feature["log"] = {"active": True, "logger": logger}
|
|
201
|
+
if has_feature("debug"):
|
|
202
|
+
feature["debug"] = {"active": True, "onEntry": capture("debug")}
|
|
203
|
+
if has_feature("audit"):
|
|
204
|
+
feature["audit"] = {"active": True, "sink": capture("audit")}
|
|
205
|
+
if has_feature("telemetry"):
|
|
206
|
+
feature["telemetry"] = {"active": True, "exporter": capture("telemetry")}
|
|
207
|
+
if has_feature("cost"):
|
|
208
|
+
feature["cost"] = {"active": True, "sink": capture("cost")}
|
|
209
|
+
if has_feature("metrics"):
|
|
210
|
+
feature["metrics"] = {"active": True}
|
|
211
|
+
if has_feature("clienttrack"):
|
|
212
|
+
feature["clienttrack"] = {"active": True}
|
|
213
|
+
|
|
214
|
+
clean = {"values": CANARY["value"]}
|
|
215
|
+
clean.update(cleanopts or {})
|
|
216
|
+
|
|
217
|
+
return ${Name}SDK({
|
|
218
|
+
"apikey": CANARY["apikey"],
|
|
219
|
+
"secret": CANARY["secret"],
|
|
220
|
+
"headers": {"X-Custom-Token": CANARY["header"]},
|
|
221
|
+
"clean": clean,
|
|
222
|
+
"feature": feature,
|
|
223
|
+
"extend": [_CaptureFeature(sinks)] + list(extra or []),
|
|
224
|
+
"utility": {"fetcher": lambda ctx, url, fetchdef: respond(url, fetchdef)},
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# The first operation that completes against a plain 200: with no
|
|
229
|
+
# arguments, else with every path parameter its points declare filled in.
|
|
230
|
+
def _usable_op():
|
|
231
|
+
def plain():
|
|
232
|
+
return ${Name}SDK({
|
|
233
|
+
"apikey": CANARY["apikey"],
|
|
234
|
+
"utility": {"fetcher": lambda ctx, url, fetchdef: (_response(200, {"id": "i1"}), None)},
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
client = plain()
|
|
238
|
+
entities = (client.get_root_ctx().config or {}).get("entity") or {}
|
|
239
|
+
found = {}
|
|
240
|
+
for attr in dir(client):
|
|
241
|
+
if not attr[:1].isupper():
|
|
242
|
+
continue
|
|
243
|
+
acc = getattr(client, attr, None)
|
|
244
|
+
if not callable(acc):
|
|
245
|
+
continue
|
|
246
|
+
try:
|
|
247
|
+
ent = acc()
|
|
248
|
+
except Exception:
|
|
249
|
+
continue
|
|
250
|
+
getname = getattr(ent, "get_name", None)
|
|
251
|
+
if not callable(getname):
|
|
252
|
+
continue
|
|
253
|
+
name = getname()
|
|
254
|
+
if isinstance(name, str) and name != "":
|
|
255
|
+
found[name] = (attr, ent)
|
|
256
|
+
|
|
257
|
+
safe = {"list": 0, "load": 1}
|
|
258
|
+
for name in sorted(found):
|
|
259
|
+
accessor, ent = found[name]
|
|
260
|
+
ops = [op for op in ["list", "load", "create", "update", "remove"]
|
|
261
|
+
if callable(getattr(ent, op, None))]
|
|
262
|
+
ops.sort(key=lambda o: safe.get(o, 2))
|
|
263
|
+
opdefs = (entities.get(name) or {}).get("op") or {}
|
|
264
|
+
for op in ops:
|
|
265
|
+
filled = {}
|
|
266
|
+
for point in (opdefs.get(op) or {}).get("points") or []:
|
|
267
|
+
for p in ((point or {}).get("args") or {}).get("params") or []:
|
|
268
|
+
if isinstance((p or {}).get("name"), str):
|
|
269
|
+
filled[p["name"]] = "p1"
|
|
270
|
+
for match in [{}, filled]:
|
|
271
|
+
try:
|
|
272
|
+
getattr(getattr(plain(), accessor)(), op)(dict(match), {})
|
|
273
|
+
return (accessor, op, match)
|
|
274
|
+
except Exception:
|
|
275
|
+
continue
|
|
276
|
+
return None
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# A feature that raises from inside the pipeline, quoting the request it
|
|
280
|
+
# saw: an error make_error never handled. Its PreUnexpected variant raises
|
|
281
|
+
# where that hook fires: make_error, and the catch path before its cleaning.
|
|
282
|
+
class _ThrowFeature(${Name}BaseFeature):
|
|
283
|
+
def __init__(self, response=True, unexpected=False):
|
|
284
|
+
super().__init__()
|
|
285
|
+
self.name = "throwhook"
|
|
286
|
+
self.version = "0.0.1"
|
|
287
|
+
self.active = True
|
|
288
|
+
self._response = response
|
|
289
|
+
self._unexpected = unexpected
|
|
290
|
+
|
|
291
|
+
def init(self, ctx, options):
|
|
292
|
+
pass
|
|
293
|
+
|
|
294
|
+
def PreResponse(self, ctx):
|
|
295
|
+
if self._response:
|
|
296
|
+
raise RuntimeError("hook saw " + json.dumps(vars(ctx.spec), default=str))
|
|
297
|
+
|
|
298
|
+
def PreUnexpected(self, ctx):
|
|
299
|
+
if self._unexpected:
|
|
300
|
+
raise RuntimeError("hook saw " + json.dumps(vars(ctx.spec), default=str))
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
# A stream that fails while the caller iterates it, quoting a credential.
|
|
304
|
+
class _StreamThrowFeature(${Name}BaseFeature):
|
|
305
|
+
def __init__(self):
|
|
306
|
+
super().__init__()
|
|
307
|
+
self.name = "streamthrow"
|
|
308
|
+
self.version = "0.0.1"
|
|
309
|
+
self.active = True
|
|
310
|
+
|
|
311
|
+
def init(self, ctx, options):
|
|
312
|
+
pass
|
|
313
|
+
|
|
314
|
+
def PreDone(self, ctx):
|
|
315
|
+
def fail():
|
|
316
|
+
raise RuntimeError("stream saw " + CANARY["apikey"])
|
|
317
|
+
yield
|
|
318
|
+
ctx.result.stream = fail
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
# A stream that succeeds, so the pipeline's terminal step never runs.
|
|
322
|
+
class _StreamOkFeature(${Name}BaseFeature):
|
|
323
|
+
def __init__(self):
|
|
324
|
+
super().__init__()
|
|
325
|
+
self.name = "streamok"
|
|
326
|
+
self.version = "0.0.1"
|
|
327
|
+
self.active = True
|
|
328
|
+
|
|
329
|
+
def init(self, ctx, options):
|
|
330
|
+
pass
|
|
331
|
+
|
|
332
|
+
def PreDone(self, ctx):
|
|
333
|
+
data = ctx.result.resdata
|
|
334
|
+
items = data if isinstance(data, list) else ([] if data is None else [data])
|
|
335
|
+
ctx.result.stream = lambda: iter(items)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _drive(sdk, target, ctrl, sinks):
|
|
339
|
+
# A caller may keep the record it passed rather than read ctrl["explain"].
|
|
340
|
+
held = ctrl.get("explain")
|
|
341
|
+
out = None
|
|
342
|
+
err = None
|
|
343
|
+
try:
|
|
344
|
+
out = getattr(getattr(sdk, target[0])(), target[1])(dict(target[2]), ctrl)
|
|
345
|
+
except Exception as e:
|
|
346
|
+
err = e
|
|
347
|
+
if err is not None:
|
|
348
|
+
sinks.extend(_forms("error", err))
|
|
349
|
+
if out is not None:
|
|
350
|
+
sinks.extend(_forms("result", out))
|
|
351
|
+
if ctrl.get("explain") is not None:
|
|
352
|
+
sinks.extend(_forms("explain", ctrl["explain"]))
|
|
353
|
+
if held is not None and held is not ctrl.get("explain"):
|
|
354
|
+
sinks.extend(_forms("explain:held", held))
|
|
355
|
+
return err
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class TestClean:
|
|
359
|
+
|
|
360
|
+
def test_no_credential_leaves_the_sdk_in_any_form(self):
|
|
361
|
+
target = _usable_op()
|
|
362
|
+
if target is None:
|
|
363
|
+
pytest.skip(NO_OP)
|
|
364
|
+
|
|
365
|
+
sinks = []
|
|
366
|
+
errors = {}
|
|
367
|
+
explains = {}
|
|
368
|
+
|
|
369
|
+
for sname, respond in SCENARIOS:
|
|
370
|
+
for vname, make_ctrl in [
|
|
371
|
+
("throw", lambda: {}),
|
|
372
|
+
("explain", lambda: {"explain": {}}),
|
|
373
|
+
("nothrow", lambda: {"throw": False, "explain": {}}),
|
|
374
|
+
]:
|
|
375
|
+
sdk = _make_sdk(respond, sinks)
|
|
376
|
+
ctrl = make_ctrl()
|
|
377
|
+
err = _drive(sdk, target, ctrl, sinks)
|
|
378
|
+
key = sname + "/" + vname
|
|
379
|
+
if err is not None:
|
|
380
|
+
errors[key] = err
|
|
381
|
+
if ctrl.get("explain") is not None:
|
|
382
|
+
explains[key] = ctrl["explain"]
|
|
383
|
+
sinks.extend(_forms("sdk", sdk))
|
|
384
|
+
sinks.append(("sdk:vars", json.dumps(vars(sdk), default=repr)))
|
|
385
|
+
|
|
386
|
+
# A credential mistyped as a map is rejected by validation, whose
|
|
387
|
+
# message quotes the value it rejected.
|
|
388
|
+
rejected = None
|
|
389
|
+
try:
|
|
390
|
+
${Name}SDK({"apikey": {"value": CANARY["apikey"]}, "clean": {"values": CANARY["value"]}})
|
|
391
|
+
except Exception as e:
|
|
392
|
+
rejected = e
|
|
393
|
+
assert rejected is not None, "a credential mistyped as a map should be rejected"
|
|
394
|
+
sinks.extend(_forms("rejected", rejected))
|
|
395
|
+
|
|
396
|
+
# An error a feature hook raises, quoting the request, skips make_error,
|
|
397
|
+
# as does the explain record it interrupts. The variant raising only in
|
|
398
|
+
# PreUnexpected reaches make_error's own firing through a 404.
|
|
399
|
+
for respond, hook in [
|
|
400
|
+
(SCENARIOS[0][1], _ThrowFeature()),
|
|
401
|
+
(SCENARIOS[0][1], _ThrowFeature(unexpected=True)),
|
|
402
|
+
(SCENARIOS[1][1], _ThrowFeature(response=False, unexpected=True))]:
|
|
403
|
+
hooked = _make_sdk(respond, sinks, None, [hook])
|
|
404
|
+
hookerr = _drive(hooked, target, {"explain": {}}, sinks)
|
|
405
|
+
assert hookerr is not None, "the throwing hook should fail the operation"
|
|
406
|
+
|
|
407
|
+
# Iterating a stream runs inside the same catch path as the operation,
|
|
408
|
+
# and the explain record the caller passed is cleaned however it ends.
|
|
409
|
+
for name, extra in [("stream", [_StreamThrowFeature()]),
|
|
410
|
+
("stream-ok", [_StreamOkFeature()]), ("stream-plain", [])]:
|
|
411
|
+
streamed = _make_sdk(SCENARIOS[0][1], sinks, None, extra)
|
|
412
|
+
explain = {}
|
|
413
|
+
streamerr = None
|
|
414
|
+
try:
|
|
415
|
+
for _item in getattr(streamed, target[0])().stream(
|
|
416
|
+
target[1], {"reqmatch": dict(target[2])}, {"ctrl": {"explain": explain}}):
|
|
417
|
+
pass
|
|
418
|
+
except Exception as e:
|
|
419
|
+
streamerr = e
|
|
420
|
+
assert ("stream" == name) == (streamerr is not None), name + ": only the failing stream raises"
|
|
421
|
+
if streamerr is not None:
|
|
422
|
+
sinks.extend(_forms(name, streamerr))
|
|
423
|
+
assert 0 < len(explain), name + ": the explain record was not filled"
|
|
424
|
+
sinks.extend(_forms(name + ":explain", explain))
|
|
425
|
+
|
|
426
|
+
# A registered value used as a property name is masked; names that
|
|
427
|
+
# mask alike are kept apart.
|
|
428
|
+
util = hooked.get_utility()
|
|
429
|
+
rootctx = hooked.get_root_ctx()
|
|
430
|
+
named = util.clean(rootctx, {CANARY["value"]: 1, CANARY["header"]: 2, "plain": 3})
|
|
431
|
+
sinks.extend(_forms("named", named))
|
|
432
|
+
assert named == {MASK: 1, MASK + "#1": 2, "plain": 3}, named
|
|
433
|
+
err = RuntimeError("boom")
|
|
434
|
+
setattr(err, CANARY["value"], "x")
|
|
435
|
+
util.clean(rootctx, err)
|
|
436
|
+
sinks.extend(_forms("named-error", err))
|
|
437
|
+
assert CANARY["value"] not in vars(err) and vars(err).get(MASK) == "x", vars(err)
|
|
438
|
+
|
|
439
|
+
# The generated config's own clean block is read beside the caller's,
|
|
440
|
+
# and is not changed by it.
|
|
441
|
+
cfgclean = {"keys": "zzsens", "values": CANARY["config"]}
|
|
442
|
+
built = util.make_options(util.make_context({
|
|
443
|
+
"utility": util,
|
|
444
|
+
"config": {"options": {"clean": cfgclean}},
|
|
445
|
+
"options": {"clean": {"values": CANARY["value"]}},
|
|
446
|
+
}, None))
|
|
447
|
+
cfgctx = util.make_context({"options": built}, None)
|
|
448
|
+
seeded = util.clean(cfgctx, "config " + CANARY["config"] + " caller " + CANARY["value"])
|
|
449
|
+
sinks.append(("config-clean", seeded))
|
|
450
|
+
assert seeded == "config " + MASK + " caller " + MASK, seeded
|
|
451
|
+
bykey = util.clean(cfgctx, {"my_zzsens": "x", "other": "y"})
|
|
452
|
+
assert bykey == {"my_zzsens": MASK, "other": "y"}, bykey
|
|
453
|
+
assert cfgclean == {"keys": "zzsens", "values": CANARY["config"]}, cfgclean
|
|
454
|
+
|
|
455
|
+
# With no clean option at all, the schema defaults still apply.
|
|
456
|
+
bare = ${Name}SDK({
|
|
457
|
+
"apikey": CANARY["apikey"],
|
|
458
|
+
"secret": CANARY["secret"],
|
|
459
|
+
"headers": {"X-Custom-Token": CANARY["header"]},
|
|
460
|
+
"utility": {"fetcher": lambda ctx, url, fetchdef: SCENARIOS[1][1](url, fetchdef)},
|
|
461
|
+
})
|
|
462
|
+
assert _drive(bare, target, {"explain": {}}, sinks) is not None, "the 404 should fail"
|
|
463
|
+
|
|
464
|
+
# A feature's name is not a field name: only the sensitive names
|
|
465
|
+
# inside its settings register. An entity block, of per-entity
|
|
466
|
+
# settings or seeded records keyed by entity name and id, is not read.
|
|
467
|
+
featured = ${Name}SDK({
|
|
468
|
+
"apikey": CANARY["apikey"],
|
|
469
|
+
"feature": {
|
|
470
|
+
"zzsecrets": {"active": False, "kind": "PLAINSETTING-q8w2e4r6"},
|
|
471
|
+
"zzfeat": {"active": False, "apitoken": "FEATTOKEN-z9y8x7w6"},
|
|
472
|
+
"test": {"active": False, "entity": {
|
|
473
|
+
"zztoken": {"ZZTOKEN01": {"note": "PLAINRECORD-t5r3e1w9"}}}},
|
|
474
|
+
},
|
|
475
|
+
"entity": {"zztoken": {"alias": {"zzkey": "PLAINALIAS-m2n4b6v8"}}},
|
|
476
|
+
})
|
|
477
|
+
fclean = featured.get_utility().clean
|
|
478
|
+
froot = featured.get_root_ctx()
|
|
479
|
+
fplain = fclean(froot, "kind PLAINSETTING-q8w2e4r6")
|
|
480
|
+
ftoken = fclean(froot, "token FEATTOKEN-z9y8x7w6")
|
|
481
|
+
frecord = fclean(froot, "record PLAINRECORD-t5r3e1w9")
|
|
482
|
+
falias = fclean(froot, "alias PLAINALIAS-m2n4b6v8")
|
|
483
|
+
|
|
484
|
+
leaked = [(name, _leaks(text)) for name, text in sinks]
|
|
485
|
+
leaked = [(name, found) for name, found in leaked if 0 < len(found)]
|
|
486
|
+
|
|
487
|
+
print("clean: swept " + str(len(sinks)) + " surface(s), " + str(len(leaked)) + " leak(s)")
|
|
488
|
+
|
|
489
|
+
assert len(leaked) == 0, "credential leaked through: " + "; ".join(
|
|
490
|
+
name + " [" + ", ".join(found) + "]" for name, found in leaked)
|
|
491
|
+
|
|
492
|
+
# The positive half: the slot the credential travelled in is masked,
|
|
493
|
+
# and an unregistered token in a response header is masked by name.
|
|
494
|
+
notfound = errors.get("notfound/throw")
|
|
495
|
+
assert notfound is not None, "the 404 scenario must raise"
|
|
496
|
+
assert notfound.status == 404
|
|
497
|
+
spec = notfound.spec or {}
|
|
498
|
+
if not AUTH["suppressed"]:
|
|
499
|
+
if "query" == AUTH["where"]:
|
|
500
|
+
assert _header(spec.get("query"), AUTH["name"]) == MASK
|
|
501
|
+
elif "cookie" == AUTH["where"]:
|
|
502
|
+
cookie = str(_header(spec.get("headers"), "cookie"))
|
|
503
|
+
assert MASK in cookie, "cookie: " + cookie
|
|
504
|
+
else:
|
|
505
|
+
cred = str(_header(spec.get("headers"), AUTH["name"]))
|
|
506
|
+
assert cred.endswith(MASK), AUTH["name"] + ": " + cred
|
|
507
|
+
assert _header(spec.get("headers"), "x-custom-token") == MASK
|
|
508
|
+
|
|
509
|
+
coded = errors.get("coded/throw")
|
|
510
|
+
assert coded is not None and coded.code == "denied_" + MASK, repr(coded)
|
|
511
|
+
|
|
512
|
+
assert fplain == "kind PLAINSETTING-q8w2e4r6", fplain
|
|
513
|
+
assert ftoken == "token " + MASK, ftoken
|
|
514
|
+
assert frecord == "record PLAINRECORD-t5r3e1w9", frecord
|
|
515
|
+
assert falias == "alias PLAINALIAS-m2n4b6v8", falias
|
|
516
|
+
|
|
517
|
+
explained = explains.get("ok/explain") or {}
|
|
518
|
+
assert explained.get("result") is not None, "the explain record should carry the result"
|
|
519
|
+
assert _header(explained["result"].get("headers"), "x-session-token") == MASK
|
|
520
|
+
|
|
521
|
+
def test_the_sweep_can_see_a_leak_with_clean_switched_off(self):
|
|
522
|
+
target = _usable_op()
|
|
523
|
+
if target is None:
|
|
524
|
+
pytest.skip(NO_OP)
|
|
525
|
+
|
|
526
|
+
sinks = []
|
|
527
|
+
sdk = _make_sdk(SCENARIOS[1][1], sinks, {"active": False})
|
|
528
|
+
err = _drive(sdk, target, {}, sinks)
|
|
529
|
+
assert err is not None
|
|
530
|
+
|
|
531
|
+
# Explaining a failure must not cost it its error.
|
|
532
|
+
explained = _drive(_make_sdk(SCENARIOS[1][1], [], {"active": False}), target, {"explain": {}}, [])
|
|
533
|
+
assert str(explained) == str(err), "with clean off, explain lost the error: " + str(explained)
|
|
534
|
+
|
|
535
|
+
leaked = [name for name, text in sinks if 0 < len(_leaks(text))]
|
|
536
|
+
assert 0 < len(leaked), "with clean off, nothing showed the canary: the sweep is blind"
|
|
537
|
+
|
|
538
|
+
if not AUTH["suppressed"]:
|
|
539
|
+
text = json.dumps(_plain(err.spec), default=str)
|
|
540
|
+
assert CANARY["apikey"] in text or \\
|
|
541
|
+
_b64(CANARY["apikey"] + ":" + CANARY["secret"]) in text, \\
|
|
542
|
+
"the raw spec should carry the credential when clean is off"
|
|
543
|
+
`
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
export {
|
|
548
|
+
TestClean
|
|
549
|
+
}
|
|
@@ -9,6 +9,7 @@ import { cmp, each, Folder, File, Content, entityCollection,
|
|
|
9
9
|
|
|
10
10
|
import { TestEntity } from './TestEntity_py'
|
|
11
11
|
import { TestDirect } from './TestDirect_py'
|
|
12
|
+
import { TestClean } from './TestClean_py'
|
|
12
13
|
import { ReadmeExamplesTest } from './ReadmeExamplesTest_py'
|
|
13
14
|
|
|
14
15
|
|
|
@@ -53,6 +54,8 @@ class TestExists:
|
|
|
53
54
|
TestDirect({ target, entity })
|
|
54
55
|
})
|
|
55
56
|
|
|
57
|
+
TestClean({ target })
|
|
58
|
+
|
|
56
59
|
// Validate the documented python examples in the root README.
|
|
57
60
|
ReadmeExamplesTest({ target })
|
|
58
61
|
})
|