fix: display the core a request actually dials (mirror list, auth status) · Entire
fix: display the core a request actually dials (mirror list, auth status)
7fbe7bc→main·
Soph·4w ago·8 files·+277 added/-20 removed
The mirror list stderr banner re-derived its core via ResolveControlPlaneTarget, which ignores ENTIRE_TOKEN. In env-token mode the request instead dials the token's own aud, so with both ENTIRE_TOKEN and a contexts.json present the banner named a core the request never talks to. The precedence (env-token-then-active-context) lives only inside coreapi.New, and the client hid its resolved core, so every "talking to X" display site was forced to re-derive it and could get it wrong.
Add coreapi.Client.CoreOrigin() — the single source of truth for "which core am I dialing", reporting whatever was wired in (active context, NewForCluster's cluster core, or the ENTIRE_TOKEN aud). Render the mirror list banner from the live client's CoreOrigin so it can never diverge from the request; this also makes it correct (rather than suppressed) in env-token mode.
Fix entire auth status the same way: it builds its own /me client outside coreapi, so it now applies the env-token-first precedence and reports the env token's core + bearer instead of a stale active context. logout stays on the active context: it manages a stored session, which an env token lacks.
Extract auth.ParseEnvToken as the single owner of the ENTIRE_TOKEN trim/blank/aud-validation sequence, shared by coreapi.New's bypass and auth status (was duplicated inline in both).
Document the convention in CLAUDE.md: to show which core, ask the client (CoreOrigin); never re-resolve for display.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
affdb4b52da3View transcript
Changes
8
MCLAUDE.md+24
cmd/entire/cli
- Mauth.go+43/-1
auth
Menv_token.go+19
Menv_token_test.go+31
Mauth_test.go+75
Mrepo_mirror.go+13/-13
internal/coreapi
- Mclient.go+14/-6
Mclient_test.go+58
443 unmodified lines
Control-Plane Core Resolution (which core am I talking to?)
Control-plane commands dial one of three cores: the active context's (coreapi.New), a specific cluster's (coreapi.NewForCluster), or — when ENTIRE_TOKEN is set — the env token's aud (the bypass inside New/NewForCluster). This precedence lives only inside coreapi; nothing else re-derives it.
To display which core a request uses, ask the client: client.CoreOrigin(). It returns whatever was actually wired in, so the shown core can never diverge from where the request goes. Do NOT re-resolve with auth.ResolveControlPlaneTarget() for display — it only knows the active context and silently ignores both ENTIRE_TOKEN and the cluster case, so it can name a core the request never touches (this was a real bug in the mirror list banner; see repo_mirror.go and coreapi.Client.CoreOrigin).
When a command resolves auth outside a coreapi.Client (e.g. entire auth status, which builds its own /me client), it must apply the same env-token-first precedence itself — see resolveAuthStatusTarget / resolveEnvTokenStatusTarget in auth.go, which branch on auth.EnvTokenVar before falling back to the active context. logout is the deliberate exception: it manages a stored login session, which an ephemeral env token has none of, so it stays on the active context.
Session Strategy (cmd/entire/cli/strategy/)
The CLI uses a manual-commit strategy for managing session data and checkpoints.
// resolveAuthStatusTarget picks the target for entire auth status, honouring
// ENTIRE_TOKEN: when it is set the request dials the token's own aud (exactly
// as coreapi.New does), so status must report that core, not a stored context
// that the request never touches. logout deliberately does NOT use this —
// logout manages a stored login session, which an ephemeral env token has none
// of, so it stays on resolveStatusTarget (the active context).
func resolveAuthStatusTarget(ctx context.Context, listContexts contextsProvider, resolveLogin loginTokenResolver) (statusTarget, error) {
if raw, ok := os.LookupEnv(auth.EnvTokenVar); ok {
return resolveEnvTokenStatusTarget(raw)
}
return resolveStatusTarget(ctx, listContexts, resolveLogin)
}
// resolveEnvTokenStatusTarget builds the status target from ENTIRE_TOKEN via the
// shared auth.ParseEnvToken — the same trim/blank/aud validation coreapi.New
// applies — so status reports exactly the core a request would dial. The token
// is the bearer; fail-closed (a blank or malformed value errors, never falls
// back to a stored context).
func resolveEnvTokenStatusTarget(raw string) (statusTarget, error) {
coreURL, token, err := auth.ParseEnvToken(raw)
if err != nil {
return statusTarget{}, err //nolint:wrapcheck // auth.ParseEnvToken already prefixes with EnvTokenVar
}
return statusTarget{coreURL: coreURL, token: token, envToken: true}, nil
}
// ParseEnvToken is the single owner of the ENTIRE_TOKEN validation sequence
// shared by coreapi.New's bypass and entire auth status: it trims the raw
// value, enforces fail-closed that it is non-blank, and derives the control-
// plane core origin from its aud via CoreURLFromEnvToken. Callers pass the raw
// env value (presence is the caller's LookupEnv decision) and send the returned
// token verbatim as the bearer to coreURL. A blank or aud-less value is an
// error, never a silent fall-back to context resolution.
func ParseEnvToken(raw string) (coreURL, token string, err error) {
token = strings.TrimSpace(raw)
if token == "" {
return "", "", fmt.Errorf("%s is set but blank", EnvTokenVar)
}
coreURL, err = CoreURLFromEnvToken(token)
if err != nil {
return "", "", err
}
return coreURL, token, nil
}