diff --git a/sdk/go/openshell/v1/gateway/gateway.go b/sdk/go/openshell/v1/gateway/gateway.go index dde3545664..382ed789f0 100644 --- a/sdk/go/openshell/v1/gateway/gateway.go +++ b/sdk/go/openshell/v1/gateway/gateway.go @@ -166,7 +166,7 @@ func resolveAuthProvider(cfg *Config) (types.AuthProvider, error) { // Token loading is deferred to GetRequestMetadata so that // NewClient succeeds even when the token file is missing. // The error surfaces on first authentication attempt (FR-007). - return &lazyEdgeAuth{loader: &edgeTokenLoader{dir: cfg.Dir}}, nil + return &lazyEdgeAuth{dir: cfg.Dir}, nil case AuthModeOIDC: src := newDiskTokenSource(cfg.Dir) diff --git a/sdk/go/openshell/v1/gateway/token.go b/sdk/go/openshell/v1/gateway/token.go index fb19726e29..a171f29d5e 100644 --- a/sdk/go/openshell/v1/gateway/token.go +++ b/sdk/go/openshell/v1/gateway/token.go @@ -10,7 +10,6 @@ import ( "os" "path/filepath" "strings" - "sync" "time" "golang.org/x/oauth2" @@ -28,32 +27,6 @@ const ( oidcTokenFile = "oidc_token.json" ) -// edgeTokenLoader provides lazy, thread-safe loading of the edge token -// from disk. Successful loads are cached; failures are retried so a token -// created after client construction can be picked up without a restart. -type edgeTokenLoader struct { - dir string - mu sync.Mutex - token string -} - -// load returns the edge token string, reading it from disk on the first -// call. It tries edge_token first, falling back to cf_token for legacy -// compatibility. Only a successful result is cached. -func (l *edgeTokenLoader) load() (string, error) { - l.mu.Lock() - defer l.mu.Unlock() - if l.token != "" { - return l.token, nil - } - token, err := readEdgeToken(l.dir) - if err != nil { - return "", err - } - l.token = token - return token, nil -} - // readEdgeToken reads the edge token from the given directory. It tries // edge_token first, then cf_token as a legacy fallback. The file content // is trimmed of surrounding whitespace. @@ -158,14 +131,14 @@ func (d *diskTokenSource) Token() (*oauth2.Token, error) { // NewClient succeeds even when the token file is missing on disk (FR-007). // The error surfaces on the first authentication attempt. type lazyEdgeAuth struct { - loader *edgeTokenLoader + dir string } -// GetRequestMetadata loads the edge token lazily and returns it as a -// Bearer authorization header. The first load is cached by the -// underlying edgeTokenLoader. +// GetRequestMetadata reads the edge token from disk on every call and +// returns it as a Bearer authorization header. Reading each time picks up +// tokens rewritten by the CLI without a process restart. func (a *lazyEdgeAuth) GetRequestMetadata(_ context.Context, _ ...string) (map[string]string, error) { - token, err := a.loader.load() + token, err := readEdgeToken(a.dir) if err != nil { return nil, err } diff --git a/sdk/go/openshell/v1/gateway/token_test.go b/sdk/go/openshell/v1/gateway/token_test.go index e9c01b4aed..ef941a9d4e 100644 --- a/sdk/go/openshell/v1/gateway/token_test.go +++ b/sdk/go/openshell/v1/gateway/token_test.go @@ -4,6 +4,7 @@ package gateway import ( + "context" "os" "path/filepath" "testing" @@ -83,41 +84,37 @@ func TestReadEdgeToken_EmptyFallbackFile(t *testing.T) { assert.Contains(t, err.Error(), "empty") } -func TestEdgeTokenLoader_Lazy(t *testing.T) { +func TestLazyEdgeAuth_ReloadsRewrittenToken(t *testing.T) { dir := t.TempDir() - writeFile(t, dir, edgeTokenFile, "lazy-token") + writeFile(t, dir, edgeTokenFile, "old-token") - loader := &edgeTokenLoader{dir: dir} + auth := &lazyEdgeAuth{dir: dir} - // First call reads from disk. - token1, err := loader.load() + md, err := auth.GetRequestMetadata(context.Background()) require.NoError(t, err) - assert.Equal(t, "lazy-token", token1) + assert.Equal(t, "Bearer old-token", md["authorization"]) - // Remove the file. Second call should return cached value. - require.NoError(t, os.Remove(filepath.Join(dir, edgeTokenFile))) + writeFile(t, dir, edgeTokenFile, "new-token") - token2, err := loader.load() + md, err = auth.GetRequestMetadata(context.Background()) require.NoError(t, err) - assert.Equal(t, "lazy-token", token2, "should return cached token") + assert.Equal(t, "Bearer new-token", md["authorization"]) } -func TestEdgeTokenLoader_LazyError(t *testing.T) { +func TestLazyEdgeAuth_PicksUpLateToken(t *testing.T) { dir := t.TempDir() // No token files exist. - loader := &edgeTokenLoader{dir: dir} + auth := &lazyEdgeAuth{dir: dir} - // First call fails. - _, err1 := loader.load() - require.Error(t, err1) + _, err := auth.GetRequestMetadata(context.Background()) + require.ErrorIs(t, err, ErrTokenLoad) - // Write the file now. A transient load failure must not be cached. writeFile(t, dir, edgeTokenFile, "late-token") - token, err2 := loader.load() - require.NoError(t, err2) - assert.Equal(t, "late-token", token) + md, err := auth.GetRequestMetadata(context.Background()) + require.NoError(t, err) + assert.Equal(t, "Bearer late-token", md["authorization"]) } // --- T015: diskTokenSource tests ---