From 6dea2763d30b37b09a132d08cda93399752d7897 Mon Sep 17 00:00:00 2001 From: Thomas Rooney Date: Mon, 24 Aug 2026 17:43:16 +0100 Subject: [PATCH 1/2] build: re-bump speakeasy-core/client-sdk-go with registry auth fixed and regression coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-does #2117 (reverted in #2120): speakeasy-core v0.23.0 to capture the registry license token, and speakeasy-client-sdk-go v3.27.1 which restores auth on the artifacts/subscriptions operations that v3.27.0 silently dropped (generated from a composed spec that marked them 'security: []'; fixed at the source in speakeasy-registry#4707 and regenerated in speakeasy-client-sdk-go#51). Pinned to a v3.27.1 pseudo-version until the tag exists. Why nothing caught it last time: the SDK regression left every method signature unchanged — utils.PopulateSecurity simply vanished from those operations, so builds stayed green and the requests went out with no x-api-key. Registry e2e tests push/pull via oras/ocicommon credentials and never touch the generated SDK, and the only SDK callsites (registry/tagging.go PostTags, internal/remote/sources.go GetRevisions — which swallows errors) had no coverage. Two new guards: - internal/sdk/sdk_test.go: hermetic contract test asserting the x-api-key header is sent on Artifacts.PostTags and Artifacts.GetRevisions (verified to fail against v3.27.0). - integration/workflow_registry_test.go: TestRegistryFlow now finishes with 'speakeasy tag promote', exercising the platform-API auth path end-to-end (passes in 30s against prod). --- go.mod | 8 ++-- go.sum | 17 ++++--- integration/workflow_registry_test.go | 9 ++++ internal/sdk/sdk_test.go | 66 +++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 internal/sdk/sdk_test.go diff --git a/go.mod b/go.mod index c3b2dddeb..02ddd2946 100644 --- a/go.mod +++ b/go.mod @@ -50,14 +50,14 @@ require ( github.com/speakeasy-api/openapi-generation/v2 v2.932.10 github.com/speakeasy-api/sdk-gen-config v1.58.0 github.com/speakeasy-api/speakeasy-agent-mode-content v0.2.12 - github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.26.7 - github.com/speakeasy-api/speakeasy-core v0.22.2 + github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.27.1-0.20260824163359-0e1b713b1512 + github.com/speakeasy-api/speakeasy-core v0.23.0 github.com/speakeasy-api/versioning-reports v0.7.0 github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.9 github.com/spf13/viper v1.19.0 github.com/stoewer/go-strcase v1.3.1 - github.com/stretchr/testify v1.12.0 + github.com/stretchr/testify v1.12.1 go.uber.org/zap v1.28.0 goa.design/goa/v3 v3.24.1 golang.org/x/oauth2 v0.36.0 @@ -233,6 +233,7 @@ require ( github.com/spewerspew/spew v0.0.0-20230513223542-89b69fbbe2bd // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.7.1 // indirect + github.com/spyzhov/ajson v0.8.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/swaggest/jsonschema-go v0.3.79 // indirect github.com/swaggest/refl v1.4.0 // indirect @@ -262,6 +263,7 @@ require ( go.opentelemetry.io/otel/trace v1.45.0 // indirect go.opentelemetry.io/proto/otlp v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect go.yaml.in/yaml/v4 v4.0.0-rc.3 // indirect golang.org/x/crypto v0.54.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect diff --git a/go.sum b/go.sum index 019d6d738..e774060ee 100644 --- a/go.sum +++ b/go.sum @@ -558,10 +558,10 @@ github.com/speakeasy-api/sdk-gen-config v1.58.0 h1:JrDgDU3XBIidv+TXFqYBvIomfeGEQ github.com/speakeasy-api/sdk-gen-config v1.58.0/go.mod h1:kD0NPNX5yaG4j+dcCpLL0hHKQbFk6X93obp+v1XlK5E= github.com/speakeasy-api/speakeasy-agent-mode-content v0.2.12 h1:dGONbW8WLNc4uSox1/k8O4JFggHoQy1v6R9cLqbTf5M= github.com/speakeasy-api/speakeasy-agent-mode-content v0.2.12/go.mod h1:AiZRZLL+sv9uwtTHIECc1dcTgfJrXrEB5QxcAGifMkI= -github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.26.7 h1:SoWZkRlpFlv8qibCfXWrBZay1JeLS9uqJ+1cu+DFgXo= -github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.26.7/go.mod h1:k9JD6Rj0+Iizc5COoLZHyRIOGGITpKZ2qBuFFO8SqNI= -github.com/speakeasy-api/speakeasy-core v0.22.2 h1:hWJjOQVQ8GKIpqQLQYmQ54td5O5N25GD9KZ496L/Enk= -github.com/speakeasy-api/speakeasy-core v0.22.2/go.mod h1:584TlOBtX4Bks5cwrbo1OPjzP3YMvzgH/NK1HKBqoo0= +github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.27.1-0.20260824163359-0e1b713b1512 h1:o1Ufm/9UlcT+g+7hJrKHHcFOJI+x2gH2J/ETERKe2Xo= +github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.27.1-0.20260824163359-0e1b713b1512/go.mod h1:u+RMkW/w6JXMZI181XpGmcqszcmaD8sSI464D4eiUDk= +github.com/speakeasy-api/speakeasy-core v0.23.0 h1:QhyPovIUhLzl/97yJmLTqYEe3vVPVBU4XyRL9rlMC08= +github.com/speakeasy-api/speakeasy-core v0.23.0/go.mod h1:2tl8YXzZCDlAxaPvF4ILBsWpzgGg+1ZA4XH7+Vwcnh0= github.com/speakeasy-api/versioning-reports v0.7.0 h1:Q2uI1RrEiOkuudoILSu7Mtkg8+ObT/hZakAG9CD+8f0= github.com/speakeasy-api/versioning-reports v0.7.0/go.mod h1:LW5FABrvi5SBbeiD3HJYw0JZYe6Rw2Xna59pFJ2BmLI= github.com/spewerspew/spew v0.0.0-20230513223542-89b69fbbe2bd h1:csraKifkLpqDClUIbFTetjtraueL1KUhKBm6okL+ug4= @@ -576,6 +576,8 @@ github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/spyzhov/ajson v0.8.0 h1:sFXyMbi4Y/BKjrsfkUZHSjA2JM1184enheSjjoT/zCc= +github.com/spyzhov/ajson v0.8.0/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzyqMuVA= github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs= github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -592,8 +594,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.12.0 h1:K6Mr6jO9JICuend/5xzTM03ydSV3vdNRYAdPSukj8uI= -github.com/stretchr/testify v1.12.0/go.mod h1:bOYBZb5qJ00vPzWfIqBUZPaxK8jWiXc6d3ErP4Ca9Gw= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ= @@ -680,8 +682,9 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.28.0 h1:IZzaP1Fv73/T/pBMLk4VutPl36uNC+OSUh3JLG3FIjo= go.uber.org/zap v1.28.0/go.mod h1:rDLpOi171uODNm/mxFcuYWxDsqWSAVkFdX4XojSKg/Q= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go= go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= goa.design/goa/v3 v3.24.1 h1:BRCgMM+8bniJCHmsGxHSOwbz4KqnEVWyL2rb+Xo3rUo= diff --git a/integration/workflow_registry_test.go b/integration/workflow_registry_test.go index cd7b80631..8252ff11f 100644 --- a/integration/workflow_registry_test.go +++ b/integration/workflow_registry_test.go @@ -161,6 +161,15 @@ func TestRegistryFlow(t *testing.T) { // Re-run the generation. It should work. cmdErr = execute(t, temp, initialArgs...).Run() require.NoError(t, cmdErr) + + // Tag the pushed revision through the platform API. Unlike the push/pull + // above (which authenticate via oras/ocicommon), `tag promote` goes through + // the generated client SDK (Artifacts.PostTags), so this guards against the + // SDK silently dropping auth on registry operations — client-sdk-go v3.27.0 + // did exactly that (403s on every tag command, CLI v1.795.2, reverted in + // #2120) and no test noticed. + cmdErr = execute(t, temp, "tag", "promote", "-s", "test-source", "-t", "e2e-test").Run() + require.NoError(t, cmdErr) } func TestRegistryFlow_JSON(t *testing.T) { diff --git a/internal/sdk/sdk_test.go b/internal/sdk/sdk_test.go new file mode 100644 index 000000000..4d89b45f1 --- /dev/null +++ b/internal/sdk/sdk_test.go @@ -0,0 +1,66 @@ +package sdk + +import ( + "context" + "net/http" + "net/http/httptest" + "sync" + "testing" + + speakeasy "github.com/speakeasy-api/speakeasy-client-sdk-go/v3" + "github.com/speakeasy-api/speakeasy-client-sdk-go/v3/pkg/models/operations" + "github.com/speakeasy-api/speakeasy-client-sdk-go/v3/pkg/models/shared" + "github.com/stretchr/testify/require" +) + +// Guards against the SDK silently dropping auth on registry operations. +// client-sdk-go v3.27.0 was generated from a spec that marked all Artifacts +// and Subscriptions operations `security: []`, so these calls went out with +// no x-api-key header and the platform returned 403s (CLI v1.795.2, reverted +// in #2120). Nothing fails at compile time when that happens — the only +// observable difference is the missing header, which this test pins down for +// the operations the CLI actually calls. +func TestInitSDKWithKey_SendsAPIKeyOnRegistryOperations(t *testing.T) { + t.Parallel() + + var mu sync.Mutex + apiKeyByPath := map[string]string{} + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + mu.Lock() + apiKeyByPath[r.URL.Path] = r.Header.Get("x-api-key") + mu.Unlock() + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(`{}`)) + })) + defer server.Close() + + s, err := InitSDKWithKey("test-api-key", speakeasy.WithServerURL(server.URL)) + require.NoError(t, err) + + ctx := context.Background() + + // registry/tagging.go (speakeasy tag promote/apply, ci tag) + _, _ = s.Artifacts.PostTags(ctx, operations.PostTagsRequest{ + NamespaceName: "test-namespace", + AddTags: &shared.AddTags{ + RevisionDigest: "sha256:0000000000000000000000000000000000000000000000000000000000000000", + Tags: []string{"main"}, + }, + }) + + // internal/remote/sources.go hasMainRevision + _, _ = s.Artifacts.GetRevisions(ctx, operations.GetRevisionsRequest{ + NamespaceName: "test-namespace", + }) + + // The response bodies above are not representative, so the calls may + // return unmarshalling errors — all this test cares about is that the + // requests carried the API key. + mu.Lock() + defer mu.Unlock() + require.Len(t, apiKeyByPath, 2, "expected both operations to reach the server") + for path, apiKey := range apiKeyByPath { + require.Equalf(t, "test-api-key", apiKey, "request to %s was sent without the x-api-key header: the SDK dropped auth for this operation", path) + } +} From bf5075a7e7d165a5190adc16ffa2e69a82da0318 Mon Sep 17 00:00:00 2001 From: Thomas Rooney Date: Wed, 26 Aug 2026 15:37:26 +0100 Subject: [PATCH 2/2] build: pin speakeasy-client-sdk-go v3.28.0 The v3.27.1 pseudo-version pointed at speakeasy-client-sdk-go#51, which was superseded by #52 (same auth fix, regenerated from the registry-published spec after speakeasy-registry#4705/#4707 merged) and tagged as v3.28.0. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 02ddd2946..04338278a 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/speakeasy-api/openapi-generation/v2 v2.932.10 github.com/speakeasy-api/sdk-gen-config v1.58.0 github.com/speakeasy-api/speakeasy-agent-mode-content v0.2.12 - github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.27.1-0.20260824163359-0e1b713b1512 + github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.28.0 github.com/speakeasy-api/speakeasy-core v0.23.0 github.com/speakeasy-api/versioning-reports v0.7.0 github.com/spf13/cobra v1.10.2 diff --git a/go.sum b/go.sum index e774060ee..d001652ec 100644 --- a/go.sum +++ b/go.sum @@ -558,8 +558,8 @@ github.com/speakeasy-api/sdk-gen-config v1.58.0 h1:JrDgDU3XBIidv+TXFqYBvIomfeGEQ github.com/speakeasy-api/sdk-gen-config v1.58.0/go.mod h1:kD0NPNX5yaG4j+dcCpLL0hHKQbFk6X93obp+v1XlK5E= github.com/speakeasy-api/speakeasy-agent-mode-content v0.2.12 h1:dGONbW8WLNc4uSox1/k8O4JFggHoQy1v6R9cLqbTf5M= github.com/speakeasy-api/speakeasy-agent-mode-content v0.2.12/go.mod h1:AiZRZLL+sv9uwtTHIECc1dcTgfJrXrEB5QxcAGifMkI= -github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.27.1-0.20260824163359-0e1b713b1512 h1:o1Ufm/9UlcT+g+7hJrKHHcFOJI+x2gH2J/ETERKe2Xo= -github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.27.1-0.20260824163359-0e1b713b1512/go.mod h1:u+RMkW/w6JXMZI181XpGmcqszcmaD8sSI464D4eiUDk= +github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.28.0 h1:IaPKp8UFXeei8LGuPQUAzAtZlrAWGfjAeygWAikrPCA= +github.com/speakeasy-api/speakeasy-client-sdk-go/v3 v3.28.0/go.mod h1:u+RMkW/w6JXMZI181XpGmcqszcmaD8sSI464D4eiUDk= github.com/speakeasy-api/speakeasy-core v0.23.0 h1:QhyPovIUhLzl/97yJmLTqYEe3vVPVBU4XyRL9rlMC08= github.com/speakeasy-api/speakeasy-core v0.23.0/go.mod h1:2tl8YXzZCDlAxaPvF4ILBsWpzgGg+1ZA4XH7+Vwcnh0= github.com/speakeasy-api/versioning-reports v0.7.0 h1:Q2uI1RrEiOkuudoILSu7Mtkg8+ObT/hZakAG9CD+8f0=