feat(whoami): show the full resolution ladder - every configured scope's identity with the winner marked, not just the collapsed result #201

Closed
opened 2026-07-17 14:34:54 +00:00 by hexajon · 1 comment
hexajon commented 2026-07-17 14:34:54 +00:00 (Migrated from codeberg.org)

Motivation

auth whoami collapses the ADR 0025 resolution chain to a single winner plus a Source: label. When the rungs disagree - the #197 split-brain repo, where repo config said claude @ gitea.example while origin + host-keyed backend said hexajon @ codeberg.org - the collapse hides exactly the information that would have made the bug self-diagnosing. The user standing 3 scopes deep in a checkout has no way to ask "what would I be one level up, and at the user level?" short of cd-ing around and re-running whoami.

Proposal

Show every rung of the ladder, winner marked, unresolvable rungs stated as such:

Resolution ladder (first configured rung wins):
  1. environment     (not set)
  2. repo config     claude @ gitea.example          <- ACTIVE
  3. origin remote   hexajon @ codeberg.org          (token: systemd-creds)
  4. workspace scan  (n/a - inside a repo)
  5. global config   claude @ gitea.example

A healthy repo shows a boring ladder where the rungs agree; the #197 disease class shows rung 2 contradicting rung 3 on its face - no heuristic needed, the user reads the disagreement directly. This is git config --show-origin, but for identity.

Design notes

  • The rungs and their per-rung identities already exist in-process: GetCredentialsWithSource walks exactly this chain and the source labels match 1:1. The change is to KEEP each rung's answer instead of returning only the first hit.
  • Two axes per rung, both shown: the forge URL/host that rung supplies, and where that host's token would come from (env / host-keyed secure backend / plaintext git config). A rung with a host but no resolvable token says so - that is a real state (#197's repo after auth login: rung 3 gained a token, rung 2 still won).
  • Local-only by default: building the ladder needs zero API calls (the identity per rung comes from config + backend metadata). Server/repo probes stay where #200 puts them - on the active rung.
  • Token values masked as today; the ladder never widens what whoami prints of a secret.
  • Placement: below the existing summary block, so the one-glance answer stays first and the ladder serves the "why is it resolving THAT?" follow-up.
  • MCP surface: same ladder in madt_auth_whoami output, which also gives #155's dir= form a natural shape - the ladder as computed from the target dir.
  • #197 - the incident this would have made self-diagnosing.
  • #200 - active-rung cross-checks and repo probe; this issue is the passive display of all rungs.
  • #155 (open) - smallest-scope identity for dir= targets; the ladder is the general form of that answer.
## Motivation `auth whoami` collapses the ADR 0025 resolution chain to a single winner plus a `Source:` label. When the rungs disagree - the #197 split-brain repo, where repo config said `claude @ gitea.example` while origin + host-keyed backend said `hexajon @ codeberg.org` - the collapse hides exactly the information that would have made the bug self-diagnosing. The user standing 3 scopes deep in a checkout has no way to ask "what would I be one level up, and at the user level?" short of cd-ing around and re-running whoami. ## Proposal Show every rung of the ladder, winner marked, unresolvable rungs stated as such: ``` Resolution ladder (first configured rung wins): 1. environment (not set) 2. repo config claude @ gitea.example <- ACTIVE 3. origin remote hexajon @ codeberg.org (token: systemd-creds) 4. workspace scan (n/a - inside a repo) 5. global config claude @ gitea.example ``` A healthy repo shows a boring ladder where the rungs agree; the #197 disease class shows rung 2 contradicting rung 3 on its face - no heuristic needed, the user reads the disagreement directly. This is `git config --show-origin`, but for identity. ## Design notes - The rungs and their per-rung identities already exist in-process: `GetCredentialsWithSource` walks exactly this chain and the source labels match 1:1. The change is to KEEP each rung's answer instead of returning only the first hit. - Two axes per rung, both shown: the forge URL/host that rung supplies, and where that host's token would come from (env / host-keyed secure backend / plaintext git config). A rung with a host but no resolvable token says so - that is a real state (#197's repo after `auth login`: rung 3 gained a token, rung 2 still won). - Local-only by default: building the ladder needs zero API calls (the identity per rung comes from config + backend metadata). Server/repo probes stay where #200 puts them - on the active rung. - Token values masked as today; the ladder never widens what whoami prints of a secret. - Placement: below the existing summary block, so the one-glance answer stays first and the ladder serves the "why is it resolving THAT?" follow-up. - MCP surface: same ladder in `madt_auth_whoami` output, which also gives #155's dir= form a natural shape - the ladder as computed from the target dir. ## Related - #197 - the incident this would have made self-diagnosing. - #200 - active-rung cross-checks and repo probe; this issue is the passive display of all rungs. - #155 (open) - smallest-scope identity for dir= targets; the ladder is the general form of that answer.
hexajon commented 2026-07-17 18:37:50 +00:00 (Migrated from codeberg.org)

Partially delivered by the whoami reshape landing in #200's PR (the full credential resolution chain - every configured rung with its forge URL, token source, and the winner marked - now renders on both surfaces). One deliberate gap remains, so this stays open:

The implemented output shows the four credential-resolution rungs (environment, secure backend, repo git config, global git config) from GetCredentialsWithSource. This issue's body pinned a 5-rung shape along the URL-resolution axis that also surfaces an "origin remote" rung. In the default secure-backend setup, madtea.url is not written on login (origin-derived per ADR 0025), so the forge URL's winning source is often the origin remote - which the credential rung list does not show as its own entry. Consequence: in the exact split-brain scenario this issue was meant to make self-diagnosing (repo config forge != origin host), the rung list alone does not display the origin URL as a contributing source; that contradiction is surfaced by the separate cross-check warning (from #200), not the rung list itself.

Remaining work to fully close: add the URL-resolution rungs (origin remote, and any workspace-scan step) to the rendered output so the forge-URL provenance is visible alongside the credential provenance, matching this issue's pinned example. Small, well-scoped follow-up on top of the now-landed plumbing.

Partially delivered by the whoami reshape landing in #200's PR (the full credential resolution chain - every configured rung with its forge URL, token source, and the winner marked - now renders on both surfaces). One deliberate gap remains, so this stays open: The implemented output shows the four credential-resolution rungs (environment, secure backend, repo git config, global git config) from GetCredentialsWithSource. This issue's body pinned a 5-rung shape along the URL-resolution axis that also surfaces an "origin remote" rung. In the default secure-backend setup, madtea.url is not written on login (origin-derived per ADR 0025), so the forge URL's winning source is often the origin remote - which the credential rung list does not show as its own entry. Consequence: in the exact split-brain scenario this issue was meant to make self-diagnosing (repo config forge != origin host), the rung list alone does not display the origin URL as a contributing source; that contradiction is surfaced by the separate cross-check warning (from #200), not the rung list itself. Remaining work to fully close: add the URL-resolution rungs (origin remote, and any workspace-scan step) to the rendered output so the forge-URL provenance is visible alongside the credential provenance, matching this issue's pinned example. Small, well-scoped follow-up on top of the now-landed plumbing.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea#201
No description provided.