auth login should ask which scope/level to store credentials at #419
Labels
No labels
breaking
bug
documentation
enhancement
epic
good first issue
help wanted
refactoring
resolution/duplicate
resolution/invalid
resolution/wontfix
security
severity/critical
severity/high
severity/low
severity/medium
status/abandoned
status/blocked
status/needs-decision
status/needs-info
status/needs-verification
testing
upstream
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
sixfold-space/madtea#419
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem: Authenticating to a second forge overwrites the first forge's stored credentials, because there is no way to choose where the token lands. Concretely: I had working credentials for one Gitea host, then ran
auth loginfor a second forge, and it clobbered the first host's token. I was never offered a choice of scope, so a routine second-forge login silently destroyed a valid credential for a different host.Expected:
auth loginshould prompt for the storage level/scope before writing, for example:This matches madtea's own documented precedence (env, then secure backend, then per-repo git config, then global git config). The tool clearly supports both a repo level and a global level, but login does not let the user pick which one to write.
Key nuance to design for: credentials are keyed per host. Two different forges should be able to coexist, not overwrite each other. So "which level" is one axis, and "do not clobber a different host's entry" is the real bug underneath it. A per-host, per-scope store would let a global token for one forge and a repo-scoped token for another live at the same time.
Acceptance criteria:
auth loginasks for the target level, or takes a flag, for example--scope global|repo.There are two parts here: a clear bug and a design call.
The bug is data loss. A second-forge login clobbers the first forge's stored token. The store is already host-keyed, so login can write per host without overwriting a different host's entry. That half is straightforward, and I can land it on its own.
The design axis is the open one: how login picks the storage LEVEL, global git config / shared backend versus per repo. It touches the credential-storage model (ADR 0013) and the launch-scope credential boundary (ADR 0027). My lean is the issue's own proposal: prompt interactively for global-vs-repo, with a
--scope global|repoflag for the non-interactive and CI paths. What I have not settled is the default when neither the prompt nor the flag answers, for example in a script that predates the flag. I will settle that before building, and the clobber fix does not need to wait for it.Grounded this against the records. It splits into a part already decided and a part that is a real bug.
The scope-prompt ask is superseded. ADR 0025 section 2 already decided that a login is forge-wide and that there is NO storage-scope prompt. Credentials are keyed by forge host, one account per forge;
--globalis a deprecated no-op. Soauth logindoes not gain a global-vs-repo scope choice. One of the proposed options, "store in global git config", is also the plaintext path that ADR 0013's 2026-07-10 hard-rule amendment bans without--insecure-storage. That half is closed by supersedence, not open design.The clobber is real, but only on the plaintext path. The secure backends (keychain, pass, systemd-creds; the default) already key every credential by forge host, so a second-forge login cannot overwrite the first:
internal/config/keychain.go:25)madtea/<host>(internal/config/pass.go:28)token-enc-<host>(internal/config/systemd_creds.go:161)Legacy compound
(url,user)entries migrate to host keys on first use, forge-gated so a forge-A migration cannot destroy forge B (internal/config/config.go:254-263).The clobber survives only on
--insecure-storage, which writes single-slotmadtea.token/madtea.url/madtea.userwith no host in the key (internal/cmd/setup/save.go:180tointernal/config/gitconfig_writer.go:28andinternal/config/git.go:126), and a login runs global. So a second-forge--insecure-storagelogin silently destroys the first forge's plaintext token.Decision (plaintext path): refuse, do not silently overwrite. When a
--insecure-storagelogin would replace a plaintext token for a DIFFERENT forge host, fail closed with a teaching error (ADR 0023): name the existing forge host, and give the two remedies, in order:Keep the plaintext fallback single-slot by design. The secure backend stays the supported multi-forge model.
Acceptance criteria:
--insecure-storagelogin with a different host's plaintext token present refuses, names the existing host, and names both remedies. No token bytes appear in the message.--insecure-storagelogin for the SAME host still updates in place.Related: ADR 0013, ADR 0025 section 2 and its 2026-07-19 amendment (#271), ADR 0023.