auth: drop test-only seam setter, dedup repo_token test setup · Entire
auth: drop test-only seam setter, dedup repo_token test setup
e771cac→main·
toothbrush·1mo ago·3 files·+23 added/-18 removed
Review cleanup: in-package tests swap the resolveContextForCluster var directly (matching data_api_test's stub idiom), so the production setter goes away; the duplicated store-sandboxing lines move into one helper.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Sessions
7ae2626a5f50View transcript
[?
Auth Refactor: Eliminate Static FallbacksClaude Code·Fable 5.[1m]·1 step](/content/gh/entireio/cli/session/e6146684-ebfa-4f57-beff-34194cac8c2a#timeline-7ae2626a5f50/index.html)
Changes
3
cmd/entire/cli
auth
Mrepo_token.go-8
Mrepo_token_test.go+22/-9
Mexplain.go+1/-1
32 unmodified lines
33
34
35
36
37
38
39
40
41
42
43
36
37
38
32 unmodified lines
// don't reach the network. Mirrors clusterdiscovery.ResolveContextForCluster.
var resolveContextForCluster resolveContextFunc = clusterdiscovery.ResolveContextForCluster
// setResolveContextForClusterForTest overrides the cluster-discovery seam
// and returns a cleanup func. Test-only.
func setResolveContextForClusterForTest(fn resolveContextFunc) func() {
prev := resolveContextForCluster
resolveContextForCluster = fn
return func() { resolveContextForCluster = prev }
}
// repoExchangeTransportForTest, when non-nil, is the HTTP transport used by
// RepoScopedToken's exchange (and login refresh), so the wire form can be
// asserted without a live core. Production leaves it nil.
Mcmd/entire/cli/auth/repo_token.go-8
17 unmodified lines
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
27
28
29
43
44
45
46
2 unmodified lines
49
50
51
38
52
53
54
41
55
56
57
58
128 unmodified lines
187
188
189
176
177
178
190
191
192
193
181
194
195
196
197
17 unmodified lines
"github.com/entireio/cli/internal/entireclient/tokenstore"
// sandboxRepoTokenStores redirects the token store and contexts.json (the
// legacy-login migration's write target) to temp locations.
func sandboxRepoTokenStores(t *testing.T) {
t.Helper()
t.Setenv("ENTIRE_CONFIG_DIR", t.TempDir())
t.Cleanup(tokenstore.UseFileBackendForTesting(filepath.Join(t.TempDir(), "tokens.json")))
}
// stubResolveContextForCluster swaps the discovery seam for fn.
func stubResolveContextForCluster(t *testing.T, fn resolveContextFunc) {
t.Helper()
prev := resolveContextForCluster
resolveContextForCluster = fn
t.Cleanup(func() { resolveContextForCluster = prev })
}
// seedRepoTokenContext wires the two seams RepoScopedToken sits on: a
// file-backed token store holding a still-valid login JWT for a context on
// coreURL, and a discovery stub resolving any cluster to that context. The
// exchange transport is left to each test. Returns the seeded login JWT.
func seedRepoTokenContext(t *testing.T, coreURL string) string {
t.Helper()
// Sandbox the legacy-login migration's contexts.json writes.
t.Setenv("ENTIRE_CONFIG_DIR", t.TempDir())
t.Cleanup(tokenstore.UseFileBackendForTesting(filepath.Join(t.TempDir(), "tokens.json")))
sandboxRepoTokenStores(t)
svc := tokenstore.CoreKeyringService(coreURL)
jwt := makeJWT(t, fmt.Sprintf(`{"iss":%q,"handle":"alice","exp":%d}`, coreURL, time.Now().Add(2*time.Hour).Unix()))
c := &contexts.Context{Name: "alice@core", CoreURL: coreURL, Handle: "alice", KeychainService: svc}
t.Cleanup(setResolveContextForClusterForTest(
stubResolveContextForCluster(t,
func(context.Context, string, string, string, *http.Client, clusterdiscovery.DebugFunc) (*contexts.Context, error) {
return c, nil
}))
)
return jwt
}
128 unmodified lines
// failure (no eligible login, ambiguous contexts, unreachable cluster) is
// returned verbatim — never papered over with a wrong-core exchange.
func TestRepoScopedToken_DiscoveryErrorSurfaces(t *testing.T) {
t.Setenv("ENTIRE_CONFIG_DIR", t.TempDir())
t.Cleanup(tokenstore.UseFileBackendForTesting(filepath.Join(t.TempDir(), "tokens.json")))
t.Cleanup(setResolveContextForClusterForTest(
sandboxRepoTokenStores(t)
stubResolveContextForCluster(t,
func(context.Context, string, string, string, *http.Client, clusterdiscovery.DebugFunc) (*contexts.Context, error) {
return nil, errors.New("not logged in to a login server trusted by cluster x; run `entire login`")
}))
)
t.Cleanup(SetRepoExchangeTransportForTest(failRoundTripper(t)))
_, err := RepoScopedToken(context.Background(), "x.entire.io", "/gh/o/r", "pull")
Mcmd/entire/cli/auth/repo_token_test.go+22/-9
1076 unmodified lines
1077
1078
1079
1080
1080
1081
1082
1083
1076 unmodified lines
var claudeErr *claudecode.ClaudeError
switch {
case errors.As(err, &claudeErr):
switch claudeErr.Kind { //nolint:exhaustive // ClaudeErrorUnknown handled by default
switch claudeErr.Kind {
case claudecode.ClaudeErrorAuth:
label := "Claude authentication failed"
rows := []explainRow{