# auth: remove unused RemoveAllContexts

`d3427dd`→[main](/content/gh/entireio/cli/commits/main/index.html)·

toothbrush·1mo ago·2 files·+0 added/-80 removed

Dead since `logout --all` was redefined to revoke server-side sessions rather than nuke all local contexts. Nothing else references it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

## Sessions

7dc263eaaac8View transcript

[?\
Refactor Auth Commands for Session ManagementClaude Code·Opus 4.8[1m]·1 step](/content/gh/entireio/cli/session/d51ce65e-9ad9-4c0d-b6af-911eed02c1ee#timeline-7dc263eaaac8/index.html)

## Changes

2

- cmd/entire/cli/auth

- Mcontext_store.go-29

- Mcontexts_test.go-51

```
61 unmodified lines

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
65
66
67

61 unmodified lines

return nil
}

// RemoveAllContexts deletes every stored context and its keyring token — a
// full local logout. Returns the number of contexts removed. Best-effort on
// the keyring deletes; the contexts.json clear is what makes the CLI fully
// logged out.
func RemoveAllContexts() (int, error) {
	var removed int
	if err := contexts.Modify(contexts.DefaultConfigDir(), func(f *contexts.File) (bool, error) {
		if len(f.Contexts) == 0 && f.CurrentContext == "" {
			return false, nil
		}
		for _, c := range f.Contexts {
			if c.KeychainService != "" && c.Handle != "" {
				// Delete both slots: the access token and its paired refresh
				// token. Dropping the refresh slot is what actually scrubs the
				// machine — otherwise a leftover refresh token outlives logout.
				_ = tokenstore.Delete(c.KeychainService, c.Handle)                            //nolint:errcheck // best-effort; the contexts.json clear below is authoritative
				_ = tokenstore.Delete(tokenstore.RefreshService(c.KeychainService), c.Handle) //nolint:errcheck // best-effort; absent refresh slot is fine
			}
			removed++
		}
		f.Contexts = nil
		f.CurrentContext = ""
		return true, nil
	}); err != nil {
		return 0, fmt.Errorf("remove all contexts: %w", err)
	}
	return removed, nil
}

// SetCurrentContext makes name the active context. Returns an error when
// no context with that name exists (a stale current pointer is a foot-gun).
func SetCurrentContext(name string) error {
```

Mcmd/entire/cli/auth/context_store.go-29

```
268 unmodified lines

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
272
273
274

268 unmodified lines

}
}

func TestRemoveAllContexts(t *testing.T) {
	cfgDir := t.TempDir()
	t.Setenv("ENTIRE_CONFIG_DIR", cfgDir)
	restore := tokenstore.UseFileBackendForTesting(filepath.Join(t.TempDir(), "tokens.json"))
	t.Cleanup(restore)

exp := time.Now().Add(time.Hour).Unix()
	if _, err := RecordLoginContext(makeJWT(t, fmt.Sprintf(`{"iss":"https://a.example.com","handle":"alice","exp":%d}`, exp)), "entr_a", true); err != nil {
		t.Fatalf("record a: %v", err)
	}
	if _, err := RecordLoginContext(makeJWT(t, fmt.Sprintf(`{"iss":"https://b.example.com","handle":"bob","exp":%d}`, exp)), "entr_b", true); err != nil {
		t.Fatalf("record b: %v", err)
	}
	n, err := RemoveAllContexts()
	if err != nil {
		t.Fatalf("RemoveAllContexts: %v", err)
	}
	if n != 2 {
		t.Fatalf("removed %d, want 2", n)
	}
	f, err := contexts.Load(cfgDir)
	if err != nil {
		t.Fatalf("load: %v", err)
	}
	if len(f.Contexts) != 0 || f.CurrentContext != "" {
		t.Fatalf("expected fully cleared, got contexts=%d current=%q", len(f.Contexts), f.CurrentContext)
	}
	// Every refresh slot must be gone too, for both removed contexts.
	for _, tc := range []struct{ iss, handle string }{
		{"https://a.example.com", "alice"},
		{"https://b.example.com", "bob"},
	} {
		svc := tokenstore.CoreKeyringService(tc.iss)
		if v, err := tokenstore.Get(svc, tc.handle); !errors.Is(err, tokenstore.ErrNotFound) {
			t.Fatalf("access slot for %s survived: value=%q err=%v", tc.handle, v, err)
		}
		if v, err := tokenstore.Get(tokenstore.RefreshService(svc), tc.handle); !errors.Is(err, tokenstore.ErrNotFound) {
			t.Fatalf("refresh slot for %s survived: value=%q err=%v", tc.handle, v, err)
		}
	}

// Idempotent.
	n2, err := RemoveAllContexts()
	if err != nil {
		t.Fatalf("second RemoveAllContexts: %v", err)
	}
	if n2 != 0 {
		t.Fatalf("second call removed %d, want 0", n2)
	}
}

func TestRemoveCurrentContext_DoesNotSwitchToAnother(t *testing.T) {
	cfgDir := t.TempDir()
	t.Setenv("ENTIRE_CONFIG_DIR", cfgDir)
