From fb403b618e3727cdbad46fe4a99bee925825bd81 Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 00:38:41 +0100 Subject: [PATCH] chore(deps): qualify ID OAuth and concurrency updates Split the remaining non-database dependency proposal into a coherent main candidate. Retain testify's required YAML update and prove history ID round trips, OAuth refresh rotation and cancellation alongside existing concurrency consumers. Contract-Neutral: Dependency and compatibility-test maintenance only; no authentication policy, API, deployment, platform support or privacy contract changes. Change-source: pulse-maintainer --- go.mod | 10 ++--- go.sum | 10 +++++ internal/api/oidc_service_additional_test.go | 46 ++++++++++++++++++++ internal/updates/history_test.go | 23 ++++++++++ 4 files changed, 84 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 8e1ffdf55..8994932b9 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/klauspost/compress v1.19.1 github.com/moby/moby/api v1.56.0 github.com/moby/moby/client v0.6.0 - github.com/oklog/ulid/v2 v2.1.1 + github.com/oklog/ulid/v2 v2.1.2 github.com/opencontainers/image-spec v1.1.1 github.com/prometheus/client_golang v1.24.1 github.com/prometheus/client_model v0.6.3 @@ -27,11 +27,11 @@ require ( github.com/rs/zerolog v1.35.1 github.com/shirou/gopsutil/v4 v4.26.8 github.com/spf13/cobra v1.10.2 - github.com/stretchr/testify v1.11.1 + github.com/stretchr/testify v1.12.1 github.com/stripe/stripe-go/v82 v82.5.1 golang.org/x/crypto v0.56.0 - golang.org/x/oauth2 v0.36.0 - golang.org/x/sync v0.22.0 + golang.org/x/oauth2 v0.37.0 + golang.org/x/sync v0.23.0 golang.org/x/sys v0.48.0 golang.org/x/term v0.45.0 gopkg.in/yaml.v3 v3.0.1 @@ -109,7 +109,7 @@ require ( go.opentelemetry.io/otel/metric v1.44.0 // indirect go.opentelemetry.io/otel/trace v1.44.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect golang.org/x/net v0.57.0 // indirect golang.org/x/text v0.41.0 // indirect golang.org/x/time v0.15.0 // indirect diff --git a/go.sum b/go.sum index 2595794ed..a584673e4 100644 --- a/go.sum +++ b/go.sum @@ -160,6 +160,8 @@ github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOF github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/oklog/ulid/v2 v2.1.2 h1:IEclFb9JNvzYA6MW2SCxbLzcHTVsfqm3PrqGQJH5zec= +github.com/oklog/ulid/v2 v2.1.2/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= @@ -222,6 +224,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/stripe/stripe-go/v82 v82.5.1 h1:05q6ZDKoe8PLMpQV072obF74HCgP4XJeJYoNuRSX2+8= github.com/stripe/stripe-go/v82 v82.5.1/go.mod h1:majCQX6AfObAvJiHraPi/5udwHi4ojRvJnnxckvHrX8= github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA= @@ -254,6 +258,8 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= 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= golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk= @@ -262,9 +268,13 @@ golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/oauth2 v0.37.0 h1:JUlcxA8oAtauLfiH8FX2/FkAWHAdi0QtGCGc+hofE98= +golang.org/x/oauth2 v0.37.0/go.mod h1:IxwZNxUULJmpBFf9K/9NTMSIfZZuvuTy1gGxhigP/58= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= +golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/api/oidc_service_additional_test.go b/internal/api/oidc_service_additional_test.go index 5f0efcd59..67d8cdd1e 100644 --- a/internal/api/oidc_service_additional_test.go +++ b/internal/api/oidc_service_additional_test.go @@ -4,6 +4,7 @@ import ( "context" "crypto/sha256" "encoding/base64" + "errors" "fmt" "io" "net/http" @@ -510,3 +511,48 @@ func TestGenerateRandomURLString_ErrorSize(t *testing.T) { t.Fatalf("expected no error for size 0, got %v", err) } } + +// TestOIDCRefreshDependencyContract exercises the real OAuth transport through +// Pulse's adapter, including providers that do not rotate refresh tokens. +func TestOIDCRefreshDependencyContract(t *testing.T) { + for _, rotate := range []bool{false, true} { + t.Run(fmt.Sprint("rotate=", rotate), func(t *testing.T) { + server := newIPv4HTTPServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if err := r.ParseForm(); err != nil { + t.Error(err) + w.WriteHeader(400) + return + } + if r.Form.Get("grant_type") != "refresh_token" || r.Form.Get("refresh_token") != "old-refresh" { + t.Error("refresh request lost grant or token") + w.WriteHeader(400) + return + } + w.Header().Set("Content-Type", "application/json") + extra := "" + if rotate { + extra = `,"refresh_token":"rotated"` + } + fmt.Fprintf(w, `{"access_token":"access","token_type":"Bearer","expires_in":3600%s}`, extra) + })) + defer server.Close() + svc := &OIDCService{oauth2Cfg: &oauth2.Config{ClientID: "client", Endpoint: oauth2.Endpoint{TokenURL: server.URL}}, httpClient: server.Client()} + result, err := svc.RefreshToken(context.Background(), "old-refresh") + if err != nil { + t.Fatal(err) + } + want := "old-refresh" + if rotate { + want = "rotated" + } + if result.RefreshToken != want || result.AccessToken != "access" || !result.Expiry.After(time.Now()) { + t.Fatal("refresh response was not preserved") + } + ctx, cancel := context.WithCancel(context.Background()) + cancel() + if _, err := svc.RefreshToken(ctx, "old-refresh"); !errors.Is(err, context.Canceled) { + t.Fatalf("cancelled refresh error = %v", err) + } + }) + } +} diff --git a/internal/updates/history_test.go b/internal/updates/history_test.go index fff3d7fd6..4a84000ad 100644 --- a/internal/updates/history_test.go +++ b/internal/updates/history_test.go @@ -7,6 +7,9 @@ import ( "path/filepath" "testing" "time" + + "github.com/oklog/ulid/v2" + "github.com/stretchr/testify/require" ) func TestNewUpdateHistory(t *testing.T) { @@ -865,3 +868,23 @@ func contains(s, substr string) bool { } return false } + +// TestUpdateHistoryIDDependencyContract protects persisted ID encoding and +// uniqueness rather than only checking that the generated string is nonempty. +func TestUpdateHistoryIDDependencyContract(t *testing.T) { + h, err := NewUpdateHistory(t.TempDir()) + require.NoError(t, err) + seen := make(map[string]bool) + for range 64 { + id, err := h.CreateEntry(context.Background(), UpdateHistoryEntry{Action: "update", Status: StatusInProgress}) + require.NoError(t, err) + parsed, err := ulid.ParseStrict(id) + require.NoError(t, err) + require.Equal(t, id, parsed.String()) + require.False(t, seen[id], "duplicate history ID") + seen[id] = true + entry, err := h.GetEntry(id) + require.NoError(t, err) + require.Equal(t, id, entry.EventID) + } +}