# auth: review follow-ups — docs, single revoke func, comment renames

`af7e7cd`·  
  
Soph·1mo ago·4 files·+23 added/-58 removed

- CLAUDE.md: correct the `auth` command surface (login/logout/status/ contexts/use; drop the removed list/revoke) and document logout's --everywhere / --all-contexts flags.
- logout: have runLogout take a single caller-selected revoke func instead of both revokeCurrent+revokeAll plus an `all` bool; the command already knows --everywhere. Drop the now-obsolete TestRunLogout_AllRevokesAllSessions (selection is covered end-to-end by TestLogoutCommand_FlagMatrix) and update the simple callers.
- Fix stale method names in //nolint:wrapcheck comments left over from the Session -> AuthSession rename.

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

## Sessions

7bbdd7fd89c1View transcript

## Changes

4

- MCLAUDE.md+3/-1

- cmd/entire/cli

- Mauth.go+1/-1

- Mlogout.go+13/-19

- Mlogout_test.go+6/-37

```
32 unmodified lines

33
34
35
36
36
37
38
39
40
41

32 unmodified lines

- `configure`: bare prints help and a hint pointing at `entire agent`; flags manage non-agent settings (telemetry, git-hook installation mode, strategy options, summary provider). Agent CRUD lives under `entire agent`.
- `auth`: `login`, `logout`, `status`, `list`, `revoke`
- `auth`: `login`, `logout`, `status`, `contexts`, `use`. `logout` takes `--everywhere` (revoke every session on the active core, not just the current one) and `--all-contexts` (log out of every saved login)
- `doctor`: bare runs the scan-and-fix flow, plus `trace`, `logs`, `bundle`

Top-level lifecycle and standalone commands: `enable`, `disable`, `status`,
```

MCLAUDE.md+3/-1

```
267 unmodified lines

268
269
270
271
271
272
273
274

267 unmodified lines

// defaultListAuthSessions lists the user's active login sessions on coreURL.
func defaultListAuthSessions(ctx context.Context, coreURL, token string) ([]api.AuthSession, error) {
    return newAuthSessionsClient(coreURL, token).ListAuthSessions(ctx) //nolint:wrapcheck // ListSessions already wraps with action context
    return newAuthSessionsClient(coreURL, token).ListAuthSessions(ctx) //nolint:wrapcheck // ListAuthSessions already wraps with action context
}

// runAuthStatus reports auth state against the target core: GET /me validates
```

Mcmd/entire/cli/auth.go+1/-1

```
78 unmodified lines

79
80
81
82
83
84
85
86
82
83
84
85
89
90
86
87
88
89
90
27 unmodified lines

118
119
120
124
121
122
123
124
2 unmodified lines

127
128
129
133
130
131
132
133
137
134
135
136
137
4 unmodified lines

142
143
144
148
149
150
151
152
145
146
147
148
149
150
151
152
153
1 unmodified line

155
156
157
160
161
162
163
158
159
160

78 unmodified lines

return fmt.Errorf("context core URL check: %w", err)
            }
        }
        revokeCurrent := func(ctx context.Context) error {
            return revokeCurrentAuthSession(ctx, target.coreURL, target.token)
        }
        revokeAll := func(ctx context.Context) error {
            return revokeAllAuthSessions(ctx, target.coreURL, target.token)
        }
        revoke := func(ctx context.Context) error {
            return revokeForTarget(ctx, target.coreURL, target.token)
        }
        if err := runLogout(cmd.Context(), outW, errW,
            auth.NewContextStore(), revokeCurrent, revokeAll,
            auth.RemoveCurrentContext, api.AuthBaseURL(), everywhere); err != nil {
            auth.NewContextStore(), revoke,
            auth.RemoveCurrentContext, api.AuthBaseURL()); err != nil {
            return err
        }
        promoteNextLogin(outW, errW)
27 unmodified lines

// revokeCurrentAuthSession revokes the active session on coreURL (the family the bearer belongs to) — the default `entire logout`.
func revokeCurrentAuthSession(ctx context.Context, coreURL, token string) error {
    return newAuthSessionsClient(coreURL, token).RevokeCurrentAuthSession(ctx) //nolint:wrapcheck // RevokeCurrentSession already wraps with action context
    return newAuthSessionsClient(coreURL, token).RevokeCurrentAuthSession(ctx) //nolint:wrapcheck // RevokeCurrentAuthSession already wraps with action context
}

// revokeAllAuthSessions revokes every active login session on coreURL (the
2 unmodified lines

// failure, so one stuck session doesn't strand the rest.
func revokeAllAuthSessions(ctx context.Context, coreURL, token string) error {
    client := newAuthSessionsClient(coreURL, token)
    // ListSessions and RevokeSession already wrap with their own action
    // ListAuthSessions and RevokeAuthSession already wrap with their own action
    // context (incl. the session id), so return their errors verbatim.
    sessions, err := client.ListAuthSessions(ctx)
    if err != nil {
        return err //nolint:wrapcheck // ListSessions already wraps with "list sessions"
        return err //nolint:wrapcheck // ListAuthSessions already wraps with "list sessions"
    }
    var firstErr error
    for _, s := range sessions {
4 unmodified lines

return firstErr
}

// runLogout ends the user's login. revokeCurrent revokes just the active
// session; revokeAll (used when all is set) revokes every session on the
// active core. Either way the local keyring entry and active context are
// removed, so the CLI reports logged-out even if the server call fails.
func runLogout(ctx context.Context, outW, errW io.Writer, store tokenStore, revokeCurrent, revokeAll revokeCurrentFunc, clearContext clearContextFunc, baseURL string, all bool) error {
// runLogout ends the user's login. revoke is the caller-selected server-side
// revocation — just the active session, or every session on the active core
// when --everywhere is set. Either way the local keyring entry and active
// context are removed, so the CLI reports logged-out even if the server call fails.
func runLogout(ctx context.Context, outW, errW io.Writer, store tokenStore, revoke revokeCurrentFunc, clearContext clearContextFunc, baseURL string) error {
    token, err := store.GetToken(baseURL)
    if err != nil {
        // Fall through to the local delete: we still want the keyring entry
1 unmodified line

fmt.Fprintf(errW, "Warning: failed to read token before revocation: %v\n", err)
    }
    if token != "" {
        revoke := revokeCurrent
        if all {
            revoke = revokeAll
        }
        if err := revoke(ctx); err != nil && !api.IsHTTPErrorStatus(err, http.StatusUnauthorized) {
            // Best-effort: a transient network error shouldn't block local
            // logout. A 401 means the token is already invalid server-side,
```

Mcmd/entire/cli/logout.go+13/-19

```
66 unmodified lines

67
68
69
70
70
71
72
73
24 unmodified lines

98
99
100
101
101
102
103
104
20 unmodified lines

125
126
127
128
128
129
130
131
23 unmodified lines

155
156
157
158
158
159
160
161
22 unmodified lines

184
185
186
187
187
188
189
190
19 unmodified lines

210
211
212
213
213
214
215
216
5 unmodified lines

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
225
226
227

66 unmodified lines

}

var out, errOut bytes.Buffer
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func(context.Context) error { return nil }, func() error { return nil }, "https://entire.io", false)
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func() error { return nil }, "https://entire.io")
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
24 unmodified lines

}

var out, errOut bytes.Buffer
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func(context.Context) error { return nil }, func() error { return nil }, "https://entire.io", false)
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func() error { return nil }, "https://entire.io")
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
20 unmodified lines

}

var out, errOut bytes.Buffer
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func(context.Context) error { return nil }, func() error { return nil }, "https://entire.io", false)
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func() error { return nil }, "https://entire.io")
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
23 unmodified lines

}

var out, errOut bytes.Buffer
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func(context.Context) error { return nil }, func() error { return nil }, "https://entire.io", false)
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func() error { return nil }, "https://entire.io")
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
22 unmodified lines

}

var out, errOut bytes.Buffer
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func(context.Context) error { return nil }, func() error { return nil }, "https://entire.io", false)
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func() error { return nil }, "https://entire.io")
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
19 unmodified lines

revoke := func(context.Context) error { return nil }

var out, errOut bytes.Buffer
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func(context.Context) error { return nil }, func() error { return nil }, "https://entire.io", false)
    err := runLogout(context.Background(), &out, &errOut, store, revoke, func(context.Context) error { return nil }, "https://entire.io")
    if err == nil {
        t.Fatal("expected error, got nil")
    }
5 unmodified lines

}
}

func TestRunLogout_AllRevokesAllSessions(t *testing.T) {
    t.Parallel()

store := newMockTokenStore()
    store.tokens["https://entire.io"] = testLogoutToken

currentCalled, allCalled := false, false
    revokeCurrent := func(context.Context) error { currentCalled = true; return nil }
    revokeAll := func(context.Context) error { allCalled = true; return nil }

var out, errOut bytes.Buffer
    err := runLogout(context.Background(), &out, &errOut, store,
        revokeCurrent, revokeAll, func() error { return nil }, "https://entire.io", true)
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }

if currentCalled {
        t.Error("--everywhere should not call the current-session revoke")
    }
    if !allCalled {
        t.Error("--everywhere should call the revoke-all path")
    }
    if !store.deleted["https://entire.io"] {
        t.Fatal("local token should still be deleted under --everywhere")
    }
    if !strings.Contains(out.String(), "Logged out.") {
        t.Fatalf("stdout = %q, want to contain %q", out.String(), "Logged out.")
    }
}

func TestLogoutCmd_IsRegistered(t *testing.T) {
    t.Parallel()
