Skip to content

Explain account and Git identity selection - #14926

Draft
williammartin wants to merge 2 commits into
williammartin-multiaccount-draft-06-sshfrom
williammartin-multiaccount-draft-07-explain
Draft

williammartin wants to merge 2 commits into
williammartin-multiaccount-draft-06-sshfrom
williammartin-multiaccount-draft-07-explain

Conversation

@williammartin

@williammartin williammartin commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Prototype overview and documentation

DO NOT MERGE. This stack is almost entirely vibe coded. These drafts are for handy review and prototyping, not merging as-is.

Expect the code to be really bad in places: highly coupled, handling edge cases that do not really matter, or doing suspiciously fragile things like parsing GraphQL request bodies.

I suspect some of the suspicious code also exposes the complexity of this feature set, because account selection, Git configuration, scope precedence, worktrees, SSH and API requests all interact.

The prototype experience is the purpose, not the code. I want to find out whether the experience is useful, not defend this implementation or treat it as a design to preserve.

Description

Follow on from #14925

Overlapping bindings and ordinary Git overrides can make the effective identity difficult to understand. This PR adds gh auth use --explain, configuration provenance and structured output.

Layer 7 of an eight-part prototype review stack. This is a way to review the design and implementation in smaller pieces, not a proposal to merge the current stack as-is.

How did you test this change?

I compared the identity file and repository-local Git config with the explanation, then checked the same winning value through Git. I also exercised stronger-scope selection and missing-account diagnostics in an isolated account snapshot.

$ git config --show-origin --get user.email
file:.git/config	local@example.invalid

A missing saved account blocks rather than falls back

multiaccount-layer-7-02-A-missing-saved-account-blocks-rather-than-falls-back.mp4

Explain why the repository wins

multiaccount-layer-7-03-Explain-why-the-repository-wins.mp4

Local Git attribution has its own provenance

multiaccount-layer-7-04-Local-Git-attribution-has-its-own-provenance.mp4

Key points

The explanation distinguishes the selected authentication identity from observed Git attribution. It reports the winning Git value and file rather than assuming the identity defaults won.

A configured SSH alias is not proof of key ownership, and an explanation is not proof that a saved credential is valid. The missing-account recording removes only an isolated registration, not a real saved account.

Notes for reviewers

Read the actual local override in the wiring recording before comparing it with the explanation. This layer reports the existing configuration graph rather than adding another routing mechanism.

The recordings use the product code at this layer, not a later stack endpoint. The included offline replay scripts are supplementary and do not reproduce the live-account recordings.

Offline replay on macOS

Build this layer, then run its synthetic scenario with an absolute executable path. This is a replay instruction, not a claim that the command below was used to make the videos.

make
env -i HOME="$HOME" PATH=/usr/bin:/bin:/opt/homebrew/bin \
  /bin/bash script/multiaccount-review/07-explain.sh --gh "$PWD/bin/gh"

Authorship and follow-up

Who wrote this:

  • A human wrote it.
  • An agent wrote it under close human direction.
  • An agent wrote it independently, and no human has guided the implementation beyond the initial prompt.

Who answers review comments:

  • @username will read and reply directly. Name the account.
  • An agent will draft replies and @username will read them before they are posted.
  • Nobody has explicitly committed to replying.

Acceptance Criteria

Prototype behaviour under review:

Given bindings and ordinary Git overrides affect the current context.

When I ask for gh auth use --explain.

Then the report separates account selection, attribution and their configuration sources.

DO NOT MERGE

williammartin and others added 2 commits November 3, 2026 22:17
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 965836ef-19ac-4473-ba1f-e326ce0f106b
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 965836ef-19ac-4473-ba1f-e326ce0f106b
Copilot AI balanced review requested due to automatic review settings November 3, 2026 21:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Owner-scoped account selection can write configuration before failing checkout inspection, while account reports can incorrectly claim gh credential-helper routing despite effective helper overrides.

2 open issues
What changed in this PR

This draft prototype adds gh auth use --explain to distinguish account selection from Git attribution and show configuration sources. It extends the existing identity-routing stack without introducing another routing mechanism.

Changes:

  • Adds text and JSON explanations of identity precedence, authentication settings, Git attribution, and includes.
  • Expands account-selection help and warns about identities referencing logged-out accounts.
  • Adds explanation tests and isolated macOS replay scripts.
File Description
script/​multiaccount-review/​common.sh Provides isolated offline fixture support.
script/​multiaccount-review/​07-explain.sh Replays precedence and missing-account scenarios.
pkg/​cmd/​root/​root.go Links account flag help to the accounts topic.
pkg/​cmd/​root/​identity_help_test.go Checks unsupported account overrides stay out of auth help.
pkg/​cmd/​root/​help_topic.go Adds the accounts and identities help topic.
pkg/​cmd/​auth/​use/​worktrees_test.go Tests explanation of worktree scope and precedence.
pkg/​cmd/​auth/​use/​use.go Wires explanation flags, JSON export, and scope messages.
pkg/​cmd/​auth/​use/​use_test.go Tests explanation output and conflicting flags.
pkg/​cmd/​auth/​use/​report_test.go Tests structured reports, provenance, and account warnings.
pkg/​cmd/​auth/​use/​explanation.go Renders human-readable explanation reports.
pkg/​cmd/​auth/​switch/​switch.go Clarifies active-account versus identity selection.
pkg/​cmd/​auth/​status/​status.go Directs users to inspect scoped account choices.
pkg/​cmd/​auth/​logout/​logout.go Warns about identities retained after logout.
pkg/​cmd/​auth/​logout/​identity_test.go Tests logout warnings and binding retention.
pkg/​cmd/​auth/​identity/​identity.go Expands identity help and missing-account warnings.
internal/​identity/​store.go Exposes resolution context and descendant bindings.
internal/​identity/​store_test.go Removes two existing binding-resolution tests.
internal/​identity/​report.go Builds authentication, attribution, and configuration reports.
internal/​identity/​explanation.go Reads effective Git values and their origins.
internal/​identity/​explanation_test.go Tests inspection of an unbound repository.
internal/​identity/​account_status.go Adds missing-account diagnostics to reports.

Review effort: Balanced

Comment thread pkg/cmd/auth/use/use.go
Comment on lines +225 to +235
result, err := s.Explain(id.Host, opts.Owner, opts.Directory)
if err != nil {
return fmt.Errorf("identity applied, but could not inspect its scope: %w", err)
}
scope := "directory tree at " + result.ScopeDirectory
if result.CommonGitDir != "" {
scope = "repository " + result.CommonGitDir + " (main checkout and all worktrees)"
}
if opts.Owner != "" {
scope = "owner " + opts.Owner
}
r.Authentication.SSH = Effect{Status: "unmanaged", Detail: "Uses your usual SSH settings"}
if id := raw.Identity; id != nil {
r.Authentication.API = Effect{Status: "declared", Value: id.Account, Detail: "Uses the saved account on " + id.Host}
r.Authentication.HTTPS = Effect{Status: "declared", Value: id.Account, Detail: "Uses gh's Git credential helper"}

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants